看了一个大神的博客:点击打开链接
我认为这个拓展欧几里得差不多还是一个模版的问题,其实真正能在模版之中加入自己东西才是王者,好吧!很明显我们需要先学会模版,首先你需要会拓展欧几里得哦
按照上面的公式我们需要一步一步的去求解。
1、求出M,M=m1*m2*m3*m4*……………..mk;
2、我们需要求出Mi=M/mi;
3、然后利用拓展欧几里得求出Mi^(-1);exgcd(Mi,mi,x1,y),x1就是需要的值。
4、最后就可以求出x的值,对于每一个ai*Mi*xmod(M)相加即可
5、根据实际的情况输出x的值,如果x小于0,需要的x大于0;这是需要变换一下,x+=M;如果本来就需要负值,那就直接输出
<span style="font-size:18px;">#include<cstdio>
void exgcd(__int64 a,__int64 b,__int64 &x,__int64&y)
{
if(b==0)
{
y=0;
x=1;
return ;
}
else
{
exgcd(b,a%b,y,x);
y-=x*(a/b);
}
}
__int64 CTR(__int64 a[],__int64 m[],__int64 n)
{
__int64 M=1,i;
for(i=0;i<n;++i)
M*=m[i];
__int64 ans=0,x,y;
for(i=0;i<n;++i)
{
__int64 Mi=M/m[i];
exgcd(Mi,m[i],x,y);
ans=(ans+Mi*x*a[i])%M;
}
//按照情况而定
/*if(ans<0)
return ans+=M;
*/
return ans;
}
int main()
{
return 0;
} </span>
断断续续搞了3天才算真正的明白
假设 x=a1(mod n1) x=a2(mod n2)........一般我们学的都是互质的情况,对于不互质的
我们采用的方法是每2个方程结合成一个方程,最后变成只有一个方程的情况,输出最小解
如何进行合并呢!现在就开始介绍
x=k1*n1+a1 x=k2*n2+a2 合并化简 k1*n1=k2*n2+a2-a1,设c=a2-a1;
k1*n1+k2*n2=c;这就变成了exgcd 如果c是d=gcd(n1,n2)的整数倍才有解,不然没有解
k1*n1=c(mod n2)->k1*n1/d=c/d(mod n2/d)->k1=(c/d)*(pow(n1/d,-1))mod( n2/d);
k1=(n2/d)*y+ T (T=pow(n1/d,-1))
代入方程 x=k1*n1+a1 -> x=n1*T+a1(mod(n1*n2/d))
这里的 n1*T+a1等于 当c=d时,k1的值,这时候我们只需要k1*c/d就可以求出
#define LL long long
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(b==0)
{
y=0;
x=1;
d=a;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
LL CRT(LL a[],LL n[],LL num)
{
LL i,c,k1,k2,n1=n[0],n2,a1,a2,x1,t;
for(i=1;i<num;++i)
{
n2=n[i];a2=a[i];
c=a2-a1;
exgcd(n1,n2,d,k1,k2);
if(c%d)
{
return 0;//无解
}
x1=k1*c/d;//n1*k1+n2*k2=d (k1,k2的解是当c=d时的解)
t=n2/d;
x1=(x1%t+t)%t;//求出最小解
a1+=x1*n1;
n1=n1/d*n2;//这时候2个方程已经合并成为1个方程与下一个再次进行合并
}
return a1;
}