码迷,mamicode.com
首页 > 其他好文 > 详细

中国剩余定理实现

时间:2017-03-18 16:13:47      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:namespace   题目   printf   stream   exgcd   应该   bsp   ret   中国剩余定理   

有一些实现的易错点。。

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;
}

 

中国剩余定理实现

标签:namespace   题目   printf   stream   exgcd   应该   bsp   ret   中国剩余定理   

原文地址:http://www.cnblogs.com/linkzijun/p/6574587.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!