题目链接:http://poj.org/problem?id=1006
题意:每个人的体力,情感,智力周期分别为23,28和33天。一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。
分析:中国剩余定理的板子题
23,28,33满足两两互质,故直接套板子即可
先上模板:
//n个方程:x=a[i](mod m[i]) (0<=i<n) LL china(int n, LL *a, LL *m){ LL M = 1, ret = 0; for(int i = 0; i < n; i ++) M *= m[i]; for(int i = 0; i < n; i ++){ LL w = M / m[i]; ret = (ret + w * inv(w, m[i]) * a[i]) % M; } return (ret + M) % M; }
然后代码
#include<cstdio> typedef long long LL; const int N = 100000 + 5; void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){ if (!b) {d = a, x = 1, y = 0;} else{ ex_gcd(b, a % b, y, x, d); y -= x * (a / b); } } LL inv(LL t, LL p){//如果不存在,返回-1 LL d, x, y; ex_gcd(t, p, x, y, d); return d == 1 ? (x % p + p) % p : -1; } LL china(int n, LL *a, LL *m){//中国剩余定理 LL M = 1, ret = 0; for(int i = 0; i < n; i ++) M *= m[i]; for(int i = 0; i < n; i ++){ LL w = M / m[i]; ret = (ret + w * inv(w, m[i]) * a[i]) % M; } return (ret + M) % M; } int main(){ LL p[3], r[3], d, ans, MOD = 21252; int cas = 0; p[0] = 23; p[1] = 28; p[2] = 33; while(~scanf("%I64d%I64d%I64d%I64d", &r[0], &r[1], &r[2], &d) && (~r[0] || ~r[1] || ~r[2] || ~d)){ ans = ((china(3, r, p) - d) % MOD + MOD) % MOD; printf("Case %d: the next triple peak occurs in %I64d days.\n", ++cas, ans ? ans : 21252); } }
原文:https://www.cnblogs.com/qingjiuling/p/11386331.html