hdu 1573 (中国乘余定理)

来源:互联网 发布:yy直播笑声软件 编辑:程序博客网 时间:2024/06/05 07:47
/*1、a1,a2,a3,a4,….,ak不一定互质,所以不能够直接用中国剩余定理。2、x=b1+a1*k1,x=b2+a2*k2,所以有1b+a1*k1=b2+a2*k2  =>  a1*k1=(r2-r1) mod(a2);用扩展欧几里得可以得到最小的k1,所以x=b1+a1*k1+a1*a2/gcd(a1,a2),就这样一直替换最后剩余一个同余方程。b1就是最后的解。3、对于x=a1 mod b1,x= a2 mod b2 => a1*x'-a2*y'=b2-b1,利用欧几里德扩展定理求出最小的非负m,那么x=a1+m*b1就已知,且x最小,如果无解,整个同余式组无解同时,x+k*b1是所有满足x=a1 mod b1的解,而x+k'*b2又是所有满足x=a2 mod b2的解那么,将x+k*b1与x+k'*b2合并,得到的式子就是x+k*lcm(b1,b2)4、设d=gcd(a,n),假定对整数x和y满足d=ax+by(比如用扩展Euclid算法求出的一组解)。如果d | b,则方程ax=b(mod n)有一个解x0满足x0=x*(b/d) mod n 。特别的设e=x0+n,方程ax=b(mod n)的最小整数解x1=e mod (n/d),最大整数解x2=x1+(d-1)*(n/d)。*/#include<iostream>#include<cstdio>using namespace std;const int N=20;__int64 ExGcd(__int64 a,__int64 b,__int64 &x,__int64 &y)//欧几里得拓展{    if(b==0)    {        x=1;y=0;        return a;    }    __int64 d=ExGcd(b,a%b,x,y);    __int64 temp=x;    x=y;    y=temp-(a/b)*y;    return d;}int main(){    int t;__int64 a[N]={0},b[N]={0};    scanf("%d",&t);__int64 a1,a2,b1,b2,tempgcd,x,y;    while(t--)    {    bool flag=false;        __int64 n,m;        scanf("%I64d%I64d",&n,&m);__int64 i,j;for(i=0;i<m;i++){scanf("%I64d",&a[i]);}for(i=0;i<m;i++){scanf("%I64d",&b[i]);}a1=a[0],b1=b[0];for(i=1;i<m;i++){a2=a[i];b2=b[i];tempgcd=ExGcd(a1,a2,x,y);if(((b2-b1)%tempgcd)!=0){flag=true;b1=-1;break;}            __int64 te = (x *((b2-b1)/tempgcd)%a2+a2)%a2;            b1 = b1+ a1* te;a1=(a1*a2)/tempgcd;b1=(b1%a1+a1)%a1;}__int64 num;if(flag){printf("0\n");}else{            if(b1<0){cout<<0<<endl;continue;}if(n<b1) num = 0;else num=(n-b1)/a1 + 1;if(b1==0) --num;printf("%I64d\n",num);}    }    return 0;}

0 0
原创粉丝点击