POJ 1006 中国剩余定理

题意: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值