在POJ上有译文(原文右上角),选择语言:简体中文
求解同余方程组:
x=ai(mod mi) i=1~r, m1,m2,...,mr互质
利用中国剩余定理
令M=m1*m2*...*mr,Mi=M/mi
因为mi两两互质,所以(Mi,mi)=1
令Mi*yi=1(mod mi)的解为yi,即Mi模mi的逆元
则方程的解为:
(a1*M1*y1+a2*M2*y2+...+ar*Mr*yr)%M
方法一:用扩展欧几里德求逆元
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int M=21252; int a[3],m[3]={23,28,33}; int sp,se,si,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); int tmp=x; x=y; y=tmp-a/b*y; return d; } int main() { int cases=0,ans; int ni[3],Mi[3],x,y; //因为mi是固定的,所以可以先将对应的逆元用扩展欧几里德求出来 for(int i=0;i<3;i++){ Mi[i]=M/m[i]; exgcd(Mi[i],m[i],x,y); ni[i]=x; } while(scanf("%d%d%d%d",&sp,&se,&si,&d)!=EOF){ if(sp==-1) break; a[0]=sp;a[1]=se;a[2]=si; ans=0; for(int i=0;i<3;i++){ ans=(ans+(a[i]*Mi[i]%M)*ni[i]%M)%M; ans=(ans+M)%M; } if(ans<=d){ ans=ans+M-d; } else ans=ans-d; printf("Case %d: the next triple peak occurs in %d days.\n",++cases,ans); } return 0; }