欧几里得算法
求两个数的最大公约数 gcd(a,b)
gcd(a,b)=gcd(b,a%b)
扩展欧几里得
求出A,B的最大公约数,且求出X、Y满足 AX+BY=GCD(A,B)
当B=0时,有X=1、Y=0时等式成立。
当B>0时,在欧几里得基础上。已知GCD(A,B)=GCD(B,A%B)
递归求出X'、Y' 满足 BX'+(A%B)Y'=GCD(B,A%B)=GCD(A,B)
化简得 AY'+B(X'-A/B*Y')=GCD(A,B)
故 X=Y',Y=X'-A/B*Y'
中国剩余定理
求方程组 x≡ai (mod mi) 的解x。
其中 mi 两两互质。
解在模下是唯一的,
为
其中,而
为模
的逆元。
POJ 1006 Biorhythms
人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。
一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。
通常这三个周期的峰值不会是同一天。
现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。
然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int extend_gcd(int a,int b,int &x,int &y){
if (b==0){
x=1;y=0;
return a;
}
else{
int r=extend_gcd(b,a%b,y,x);
y=y-x*(a/b);
return r;
}
}
int CRT(int a[],int m[],int n){
int M=1;
for (int i=0;i<n;i++) M*=m[i];
int ret=0;
for (int i=0;i<n;i++){
int x,y;
int tm=M/m[i];
extend_gcd(tm,m[i],x,y);
ret=(ret+tm*x*a[i])%M;
}
return (ret+M)%M;
}
int a[5],m[5];
int main()
{
int p,e,i,d;
m[0]=23;
m[1]=28;
m[2]=33;
int cas=0;
while (~scanf("%d%d%d%d",&p,&e,&i,&d)){
if (p==-1||e==-1||i==-1||d==-1) break;
a[0]=p;
a[1]=e;
a[2]=i;
int ans=CRT(a,m,3);
ans=(ans-d+21252)%21252;
if (ans==0) ans=21252;
printf("Case %d: the next triple peak occurs in %d days.\n",++cas,ans);
}
return 0;
}