lightoj 1319 - Monkey Tradition 中国剩余定理(孙子定理)+poj 2891 Strange Way to Express Integers

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL long long
LL p[13],r[13],n;
void gcd(LL a,LL b,LL &d,LL &x,LL &y)//扩展欧几里德算法求ax+by=gcd(a,b)当然一组整数解
{                                           //其中d是最大公约数
    if(!b){d=a;x=1;y=0;}
    else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
LL Chinese_Remainder()
{
    LL i,s=1,m,x,y,d,ans=0;
    for(i=0;i<n;i++)
        s=s*p[i];
    for(i=0;i<n;i++)
    {
        m=s/p[i];
        gcd(p[i],m,d,x,y);  //p[i]与m互质,p[i]*x+my=1(y必定不是0),因而my%p[i]==1,myr[i]%p[i]=r[i];m为其余数相乘
        ans=(ans+y*m*r[i])%s;//所以总和ans只有对应的myr[i]有余数,其余都整除
    }
    return (ans%s+s)%s;
}
int main()
{
    LL T,t,tt=0,i;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        for(i=0;i<n;i++)
            scanf("%lld%lld",&p[i],&r[i]);
        t=Chinese_Remainder();
        printf("Case %lld: %lld\n",++tt,t);
    }
    return 0;
}
/*
中国剩余定理(孙子定理):求M使,M%A=a,M%B=b,M%C=c,...,M%Z=z。其中A,B,C,...,Z互质
先求第一个数:m=(B*C**...*Z);A与m互质,由扩展欧几里德算法求得(x,y)使得A*x+m*y=1
所以(A*x+my)%A-->my%A=1-->amy%A=a,amy%(B,C,D,...)=0;
求出其余的数并求和ans=a*m1*y1+b*m2*y2+c*m3*y3...就是解。由于很大,要对n=(A*B*C*...*Z)取余,不影响结果
*/


poj2891 是中国剩余定理的一般形式,其中M%m1=r1,M%m2=r2...;m1,m2...互相之间不互质

只能每输入一个求一次解,类似dp

#include <stdio.h>
#include <string.h>
void gcd(__int64 a,__int64 b,__int64 &d,__int64 &x,__int64 &y)
{//a*x+b*y=gcd(a,b)=d;(x,y)为其一组整数解
    if(!b){d=a;x=1;y=0;}
    else{ gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
int main()
{
    __int64 n,m1,r1,m2,r2,flag=0;
    while(scanf("%I64d",&n)!=EOF)
    {
        __int64 i,j,k,d,x,y,c,t;
        scanf("%I64d%I64d",&m1,&r1);
        flag=0;
        for(i=1;i<n;i++)
        {
            scanf("%I64d%I64d",&m2,&r2);
            if(flag)continue;
            gcd(m1,m2,d,x,y);//d=gcd(m1,m2);x*m1+y*m2=d;
            c=r2-r1;
            if(c%d)//对于方程m1*x+m2*y=c,如果c不是d的倍数就无整数解
            {
                flag=1;
                continue;
            }
            t=m2/d;//对于方程m1x+m2y=c=r2-r1,若(x0,y0)是一组整数解,那么(x0+k*m2/d,y0-k*m1/d)也是一组整数解(k为任意整数)
                    //其中x0=x*c/d,y0=x*c/d;
            x=(c/d*x%t+t)%t;//保证x0是正数,因为x+k*t是解,(x%t+t)%t也必定是正数解(必定存在某个k使得(x%t+t)%t=x+k*t)
            r1=m1*x+r1;//新求的r1就是前i组的解,Mi=m1*x+M(i-1)=r2-m2*y(m1为前i个m的最小公倍数);对m2取余时,余数为r2;
                        //对以前的m取余时,Mi%m=m1*x%m+M(i-1)%m=M(i-1)%m=r
            m1=m1*m2/d;
        }
        if(flag)printf("-1\n");
        else printf("%I64d\n",r1);
    }
    return 0;
}


你可能感兴趣的:(中国剩余定理)