POJ NOTES:1006 Biorhythms 中国剩余定理

阅读 题目详情

题目解析

本题是一个中国剩余定理的应用问题。

错误做法:直接用循环判定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 Ad,要求 A > d A> d A>d

中国剩余定理

POJ NOTES:1006 Biorhythms 中国剩余定理_第1张图片
POJ NOTES:1006 Biorhythms 中国剩余定理_第2张图片
POJ NOTES:1006 Biorhythms 中国剩余定理_第3张图片
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×itZ

数论中的逆元及其求法

逆元的理解
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×Mi1 mod mi=1的最小 M i − 1 M_{i}^{-1} Mi1,上图中表示为 M i − 1   m o d   m i M_{i}^{-1}\space mod\space m_{i} Mi1 mod mi

逆元的求法

  1. 枚举法
    枚举1到 p − 1 p - 1 p1的整数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的乘法逆元。(注意枚举范围)

  2. 扩展欧几里得
    求使 M i − 1 × M i   m o d   m i = 1 M_{i}^{-1}\times M_{i}\space mod\space m_{i} = 1 Mi1×Mi mod mi=1的最小 M i − 1 M_{i}^{-1} Mi1可转化为求 ( 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 Mi1×Mi +k×mimod 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) xb+y(a % b)=xb+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) ya+[xy(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=xy(a/b)
    且我们容易推出extend_Eculid中 b = 0 b=0 b=0时, x = 1 , y = 0 x=1,y=0 x=1,y=0
    可用递归代码求解,代码见下。

  3. 费马小定理
    若p 是质数, b b b是正整数且不能被 p p p整除,则有 b p − 1 ≡ 1 ( m o d   p ) b^{p-1} ≡ 1 (mod\space p) bp11(mod p)
    可推出 b p − 2   m o d   p b^{p - 2}\space mod\space p bp2 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;
}

你可能感兴趣的:(POJ,C/C++)