有一些实现的易错点。。
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 ",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 ",CRT()); } return 0; }