POJ 1006 Biorhythms(中国剩余定理)

题目传送门

http://poj.org/problem?id=1006


思路

中国剩余定理果题。

xai(modmi) 的最小正整数解。

简要说一下步骤,证明什么的网上有很多,不再赘述。

首先令 M=mi ,令 Mi=Mmi ,求出 Mi 的某个倍数使得其满足模 mi 等于 ai ,即 kMiai(modmi) ,发现 kaiM1i(modmi) ,于是 kMiaiMiM1i(modmi) ,其中 M1i Mi 关于 mi 的逆元。(正确性其实是显然的)

将所有求得的数相加得到一解,尽可能减去所有 mi lcm 即得最小解。

答案就是一条公式:

ans=aiMiM1imodM

注意答案要大于0。(话说本题暴力也可以)


代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

int d, Case, ans, MOD = 21252;
int m[5] = {0, 23, 28, 33}, M[5] = {0, 21252/23, 21252/28, 21252/33};
int A[5], InvM[5];

void Exgcd(int a, int b, int& x, int& y){
    if(!b){
        x = 1;
        y = 0;
        return;
    }
    Exgcd(b, a % b, y, x);
    y -= x * (a / b);
}

int CRT(){
    int x, y;
    for(int i = 1; i <= 3; i++){
        Exgcd(M[i], m[i], x, y);
        InvM[i] = (x % m[i] + m[i]) % m[i];
    }
    int res = 0;
    for(int i = 1; i <= 3; i++)
        res = (res + A[i] * M[i] % MOD * InvM[i] % MOD) % MOD;
    return res;
}

int main(){

    for(;;){
        for(int i = 1; i <= 3; i++)  scanf("%d", &A[i]);
        if(A[1] == -1)  break;
        scanf("%d", &d);
        ans = CRT() - d;
        if(ans <= 0)  ans += MOD;
        printf("Case %d: the next triple peak occurs in %d days.\n", ++Case, ans);
    }

    return 0;
} 

接下来要写三模数NTT。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值