POJ 1006中国余数定理


ここの問題はプログラミングの問題ではなく、厳密に言えば数学の問題です.
主に中国の余数の定理を考察する.
ここで典型的な例を挙げると、n%3=2、n%5=3、n%7=2である.nはいくらですか.
この問題の列挙はもちろん計算できるが,定理を用いて複雑度をO(1)に下げるにはどうすればよいのだろうか.
まず、5*7の倍数を求め、3余り1で割った.同様に、3*7の倍数を求め、5余り1で割った.同様に、3*5の倍数を求める、7で割る.
次に求めた3つの数を、ひとまずa,b,cと呼ぶ.簡単な演算をして、つまりsum=2*a+3*b+2*cを求めます
最後に、3,5,7の最小公倍数lcm(3,5,7)を求める.結果としてresult=sum%lcm
では、このテーマに戻って、このような式をリストすることができます.
(n+d)%23 = p
(n+d)%28 = e
(n+d)%33 = i
ここではsum=p*5544+e*14421+i*1288を求めることができます.
ここの5544144211288はどうやって得られるのか、もちろんforサイクルを借りて、条件を満たすと倍数を出力することができます.ここの倍数はそれぞれ6,19,2です.
したがって,最後の結果はresult=(sum−d+21252)%lcm(23,28,33)であった.
ここでなぜ-dを括弧の中に入れるのかは、このような状況を防止するため、結果は21252であるべきで、外に置くと0になる.例:19 0 1 364
ここで注意するのは、カッコの中に21252が入っているので、負数が出ないようにするためです
#include<iostream>
using namespace std;

int main(){
    int p,e,i,d;
    int count=1;
    int lcm = 23*28*33;
    int days;
    while(cin>>p>>e>>i>>d){
        if(p==-1&&e==-1&&i==-1&&d==-1)
            break;
        days = (5544*p+14421*e+1288*i-d)%lcm;
        days = (days+21252)%21252;    //      
        if(days == 0)
            days = 21252;
        cout<<"Case "<<count<<": the next triple peak occurs in "<<days<<" days."<<endl;
        count++;
    }
    return 0;
}