POJ 1006 中国剩余定理

来源:互联网 发布:淘宝上传食品需要证件 编辑:程序博客网 时间:2024/05/21 17:20

题意:POJ上有中文翻译,题目名称右面language可以选择简体中文。

用中国剩余定理可以轻松解决,主要靠这道题学了学中国剩余定理,然而只学会了怎么写,原理还是不太理解。

首先列出式子:
p + x1 * 23 = n;
e + x2 * 28 = n;
i + x3 * 33 = n;
输出ans = n - d % 21252;

方程组可以写为:
n ≡ p (mod 23);
n ≡ e (mod 28);
n ≡ i (mod 33);

中国剩余定理(维基百科)用于解一类一元一次同余方程组:
x ≡ a[1] (mod m[1]);
x ≡ a[2] (mod m[2]);
x ≡ a[3] (mod m[3]);
….
x ≡ a[n] (mod m[n]);
当对于任意i, j ∈ [1, n]时, m[i], m[j]互质,则对于任意a[i], i ∈ [1,n],原方程组有解:
设mul = m[1] * m[2] * m[3] …… * m[n]
设M[i] = mul / m[i];
设ni[i]为M[i] 在 mod m[i]下的逆元;
设t[i] = M[i] * ni[i];
则解为k * mul + Σt[i]*a[i], i ∈ [1, n], k ∈ Z;

这道题给21252的意思大概就是假设一年是21252天,答案对21252取模,不会出现第0天,所以ans==0输出21252。

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;int d, w[4], m[4] = {0, 23, 28, 33}, mul, t[4], cnt;void Exgcd(int a, int b, int &x, int &y){    if(!b) x = 1, y = 0;    else { Exgcd(b, a%b, y, x); y -= a/b*x;}}int get_ni(int a, int p){    int x, y;    Exgcd(a, p, x, y);    return (x+p)%p; }int main(){    mul = 23*28*33;    for(int i = 1; i < 4; i++)     {        t[i] = get_ni(mul/m[i], m[i])*mul/m[i];    }    while(scanf("%d", w+1) && w[1] >= 0)    {        for(int i = 2; i < 4; i++) scanf("%d", w+i);        scanf("%d", &d);        for(int i = 1; i < 4; i++)  w[i] %= m[i];           int ans = -d;        for(int i = 1; i < 4; i++) ans = (ans+w[i]*t[i])%21252;        while(ans <= 0) ans += 21252;        printf("Case %d: the next triple peak occurs in %d days.\n", ++cnt, ans);    }       return 0;} 
0 0
原创粉丝点击