首页 > 代码库 > exgcd&&中国剩余定理专题练习

exgcd&&中国剩余定理专题练习

hdu1573求中国剩余定理解的个数

#include <iostream>
#include <cstdio>

using namespace std;
int a[100],b[100];
int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;y=0;return a;
    }
    int d=exgcd(b,a%b,x,y),t;
    t=x;x=y;y=t-a/b*y;
    return d;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        int n,m;scanf("%d%d",&n,&m);
        for(int i=0;i<m;++i) scanf("%d",a+i);
        for(int i=0;i<m;++i) scanf("%d",b+i);
        int a1=a[0],r1=b[0],flag=0;
        for(int i=1;i<m;++i){
            int a2=a[i],r2=b[i];
            int d=r2-r1,x,y,GCD=exgcd(a1,a2,x,y);
            if(d%GCD){
                flag=1;break;
            }
            x*=d/GCD;int mod=a2/GCD;
            x=(x%mod+mod)%mod;
            r1=x*a1+r1;
            a1=a1*a2/GCD;
        }
        if(r1>n||flag) printf("0\n");
        else printf("%d\n",(n-r1)/a1+1-(r1==0?1:0));//没考虑r1==0的情况
    }
}

poj1061 列同余方程,exgcd解方程

#include <iostream>
#include <cstdio>

using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1;y=0;return a;
    }
    ll d=exgcd(b,a%b,x,y),t;
    t=x;x=y;y=t-a/b*y;
    return d;
}
int main(){
    ll x,y,m,n,L;
    while(~scanf("%I64d%I64d%I64d%I64d%I64d",&x,&y,&m,&n,&L)){
        ll rx,ry,GCD,D=((y-x)%L+L)%L,A=((m-n)%L+L)%L;
        GCD=exgcd(A,L,rx,ry);
        if(D%GCD) {
            printf("Impossible\n");continue;
        }
        ll mod=L/GCD;rx*=D/GCD;
        rx=(rx%mod+mod)%mod;
        printf("%I64d\n",rx);
    }
    return 0;
}

poj2115 不互质情况下又需要求类似逆元的东西

#include <iostream>
#include <cstdio>

using namespace std;
typedef long long ll;
ll A,B,C,k;
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0) {
        x=1;y=0;return a;
    }
    ll d=exgcd(b,a%b,x,y),t;
    t=x;x=y;y=t-a/b*y;
    return d;
}
int main(){
    while(~scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k)){
        if(A+B+C+k==0) break;
        ll n=(1ll<<(k));
        ll D=((B-A)%n+n)%n,x,y,GCD;
        GCD=exgcd(C,n,x,y);
        if(D%GCD){
            printf("FOREVER\n");continue;
        }
        ll mod=n/GCD;x*=D/GCD;
        x=(x%mod+mod)%mod;
        printf("%I64d\n",x);
    }
    return 0;
}

poj2891 一元线性方程组-不互质的中国剩余定理

#include <iostream>
#include <cstdio>

using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1;y=0;return a;
    }
    ll d=exgcd(b,a%b,x,y),t;
    t=x;x=y;y=t-a/b*y;
    return d;
}
int main(){
    ll k;
    while(~scanf("%I64d",&k)){
        ll a1,r1,a2,r2,ans;scanf("%I64d%I64d",&a1,&r1);
        int flag=0;
        for(int i=1;i<k;++i){
            scanf("%I64d%I64d",&a2,&r2);
            if(flag) continue;
            ll d=r2-r1,x,y,GCD=gcd(a1,a2);
            if(d%GCD) {
                flag=1;continue;
            }
            ll A1=a1/GCD,A2=a2/GCD,D=d/GCD;
            exgcd(A1,A2,x,y);
            x*=D;x=(x%A2+A2)%A2;
            r1=x*a1+r1;
            a1=a1*a2/GCD;
        }
        if(flag)     printf("-1\n");
        else         printf("%I64d\n",r1);
    }
    return 0;
}

poj 1006 高峰期出现的同一天,中国剩余定理

#include <iostream>
#include <cstdio>

using namespace std;
int p,e,i,d;
int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;y=0;return a;
    }
    int d=exgcd(b,a%b,x,y),t;
    t=x;x=y;y=t-a/b*y;
    return d;
}
int main(){
    int cas=0;
    while(~scanf("%d%d%d%d",&p,&e,&i,&d)){
        if(p+e+i+d==-4) break;
        int N=23*28*33,K,x,y,ans=0;
        exgcd(23,K=N/23,x,y);y=(y%23+23)%23;
        ans=(ans+K*y*(p-d))%N;
        exgcd(28,K=N/28,x,y);y=(y%28+28)%28;
        ans=(ans+K*y*(e-d))%N;
        exgcd(33,K=N/33,x,y);y=(y%33+33)%33;
        ans=(ans+K*y*(i-d))%N;
        if(ans<=0) ans+=N;
        printf("Case %d: the next triple peak occurs in %d days.\n",++cas,ans);
    }
    return 0;
}

poj2142 对exgcd得出的|s|+|t|最小的解,求s>0时t为多少,t>0时s为多少,两个方向求一下最小正整数解

#include <iostream>
#include <cstdio>

using namespace std;
int a,b,d;
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y){
    if(b==0){x=1;y=0;return a;}
    int d=exgcd(b,a%b,x,y),t;
    t=x;x=y;y=t-a/b*y;
    return d;
}
int main(){
    while(~scanf("%d%d%d",&a,&b,&d)){
        if(a+b+d==0) break;
        int GCD=gcd(a,b);
        a/=GCD,b/=GCD,d/=GCD;
        int x,y;exgcd(a,b,x,y);
        int x1,y1,x2,y2;
        x1=x*d;
        x1=(x1%b+b)%b;y1=(d-a*x1)/b;if(y1<0) y1=-y1;
        y2=y*d;
        y2=(y2%a+a)%a;x2=(d-b*y2)/a;if(x2<0) x2=-x2;
        if(x1+y1>x2+y2) {
            x1=x2;y1=y2;
        }
        printf("%d %d\n",x1,y1);
    }
    return 0;
}

 

exgcd&&中国剩余定理专题练习