中国剩余定理实现

有一些实现的易错点。。

1,exgcd忘记返回gcd值而只顾着求逆元了

2,逆元和N/m[i]对应,算出对应逆元x后,贡献的值应该是N/m[i]*x*b[i]

3,看题目数据范围,可能会爆Int,比如我最后ans本来是算对了的,但是return (ans+N)%N之后就会爆int

所以这个写法慎用。。由于每一步都取了模,我们可以return ans<0?ans+N:ans;

不管逆元的正负我们可以这么写

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
int n,m[11],b[11];
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;
}
ll CRT(){
    ll N=1,i,ans=0;
    for(i=1;i<=n;++i) N*=m[i];
    for(i=1;i<=n;++i){
        ll x,y;
        ll d=exgcd(N/m[i],m[i],x,y);
        ans=(ans+N/m[i]*x*b[i]+N)%N;
    }
    return ans<0?ans+N:ans;
}
int main(){
    while(~scanf("%d",&n)){
        int i;
        for(i=1;i<=n;++i) scanf("%d%d",m+i,b+i);
        printf("%lld\n",CRT());
    }
    return 0;
}

保证逆元大于0,最后直接返回答案就行

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
int n,m[11],b[11];
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;
}
ll CRT(){
    ll N=1,i,ans=0;
    for(i=1;i<=n;++i) N*=m[i];
    for(i=1;i<=n;++i){
        ll x,y;
        ll d=exgcd(N/m[i],m[i],x,y);
        x=(x%m[i]+m[i])%m[i];
        ans=(ans+N/m[i]*x*b[i]+N)%N;
    }
    return ans;
}
int main(){
    while(~scanf("%d",&n)){
        int i;
        for(i=1;i<=n;++i) scanf("%d%d",m+i,b+i);
        printf("%lld\n",CRT());
    }
    return 0;
}

 

posted @ 2017-03-18 16:08  狡啮之仰  阅读(243)  评论(0编辑  收藏  举报