阅读 题目详情
本题是一个中国剩余定理的应用问题。
错误做法:直接用循环判定p+k*23 == e+k*28 == i+k*33
错误原因:triple peak 中的3个peak不一定都发生在第k个period
(e.g. 第1个physical peak,第2个emotional peak 和第3个 intellectual peak是同一天)
正确求解方法
在本题中,三个不同的周期(23,28,33)相当于 m 1 , m 2 , m 3 m_1,m_2,m_3 m1,m2,m3;题目输入的 p , e , i p,e,i p,e,i相当于 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3;求 A − d A-d A−d,要求 A > d A> d A>d
PS:所有的解为 A = A 0 + t × p × e × i ( t ∈ Z ) A=A_0+t\times p\times e\times i(t∈Z) A=A0+t×p×e×i(t∈Z)
逆元的理解
M i M_{i} Mi模 m i m_{i} mi的逆元是使 M i × M i − 1 m o d m i = 1 M_{i}\times M_{i}^{-1}\space mod\space m_{i} = 1 Mi×Mi−1 mod mi=1的最小 M i − 1 M_{i}^{-1} Mi−1,上图中表示为 M i − 1 m o d m i M_{i}^{-1}\space mod\space m_{i} Mi−1 mod mi 。
逆元的求法
枚举法
枚举1到 p − 1 p - 1 p−1的整数bi,若 b × b i m o d p = 1 b\times b_i\space mod\space p = 1 b×bi mod p=1,则 b i b_i bi即为 b m o d p b\space mod\space p b mod p的乘法逆元。(注意枚举范围)
扩展欧几里得
求使 M i − 1 × M i m o d m i = 1 M_{i}^{-1}\times M_{i}\space mod\space m_{i} = 1 Mi−1×Mi mod mi=1的最小 M i − 1 M_{i}^{-1} Mi−1可转化为求 ( M i − 1 × M i + k × m i ) m o d m i = 1 (M_{i}^{-1}\times M_{i}\space+k\times m_{i}) mod\space m_{i}= 1 (Mi−1×Mi +k×mi)mod mi=1
且 M i M_{i} Mi与 m i m_{i} mi互素,即 g c d ( M i , m i ) = 1 gcd(M_{i},m_{i})=1 gcd(Mi,mi)=1。
形如:求最小 x , y x,y x,y 使得 x a + y b = g c d ( a , b ) xa+yb=gcd(a,b) xa+yb=gcd(a,b) 的问题一般均可用extend_Eculid解。
由欧几里得定理可知 g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b)=gcd(b,a\space \%\space b) gcd(a,b)=gcd(b,a % b),其中 a % b = a − ( a / b ) × b a\space \%\space b=a-(a/b)\times b a % b=a−(a/b)×b,据此推导:
x ′ b + y ′ ( a % b ) = x ′ b + y ′ [ a − ( a / b ) × b ] = g c d ( b , a % b ) x^{'}b+y^{'}(a\space \%\space b)=x^{'}b+y^{'}\left [a-(a/b)\times b \right ]=gcd(b,a\space \%\space b) x′b+y′(a % b)=x′b+y′[a−(a/b)×b]=gcd(b,a % b)
y ′ a + [ x ′ − y ′ ( a / b ) ] × b = g c d ( b , a % b ) = g c d ( a , b ) y^{'}a+\left [x^{'}-y^{'}(a/b) \right ]\times b=gcd(b,a\space \%\space b)=gcd(a,b) y′a+[x′−y′(a/b)]×b=gcd(b,a % b)=gcd(a,b)
所以有
x = y ′ x=y^{'} x=y′
y = x ′ − y ′ ( a / b ) y=x^{'}-y^{'}(a/b) y=x′−y′(a/b)
且我们容易推出extend_Eculid中 b = 0 b=0 b=0时, x = 1 , y = 0 x=1,y=0 x=1,y=0
可用递归代码求解,代码见下。
费马小定理
若p 是质数, b b b是正整数且不能被 p p p整除,则有 b p − 1 ≡ 1 ( m o d p ) b^{p-1} ≡ 1 (mod\space p) bp−1≡1(mod p)。
可推出 b p − 2 m o d p b^{p - 2}\space mod\space p bp−2 mod p 即为 b m o d p b\space mod\space p b mod p 的乘法逆元。
代码如下
#include
#include
#include
using namespace std;
//扩展欧几里得 求逆元
void ext_Euclid(int a, int b, int &x, int &y){
if(b == 0){
x = 1;
y = 0;
return;
}
ext_Euclid(b, a%b, x, y);
int temp = x;
x = y;
y = temp -(a/b)*y;
}
//中国剩余定理
int CRT(int a[], int m[], int n){
int M = 1, x, y, ans = 0;
int Mi[n];
for(int i = 0; i < n; i++)
M *= m[i];
for(int i = 0; i < n; i++){
Mi[i] = M/m[i];
ext_Euclid(Mi[i],m[i],x,y);
ans = (ans + a[i]*Mi[i]*x)%M;
}
if(ans < 0) ans += M;
return ans;
}
int main(){
int p, e, i, d, cnt = 0;
int m[3] = {23, 28, 33};
int a[3], ans;
while(cin>>p>>e>>i>>d && p!=-1 && e!=-1 && i!=-1 && d!=-1){
a[0] = p;
a[1] = e;
a[2] = i;
ans = CRT(a,m,3);
if(ans <= d) ans += 21252;
cout<<"Case "<<++cnt<<": the next triple peak occurs in "<<ans-d+1<<" days."<<endl;
}
return 0;
}