POJ 1006 Biorhythms 【中国剩余定理】

题目链接:http://poj.org/problem?id=1006

思路:

中国剩余定理总结:

n1, n2, n3; n % n1 = p; n % n2 = e; n % n3 = i;求最小正整数 n;

a * n2*n3 % n1 = 1; 等价于 a * n2*n3 - 1 = k * n1 ---> a * n2*n3 - k*n1 = 1; 通过扩展欧几里得求出 a ,exgcd (n2*n3, n1, a, k);

b * n1*n3 % n2 = 1; 等价于 b * n1*n3 - 1 = k * n2 ---> b * n1*n3 - k*n2 = 1; 同上求出 b ,exgcd (n1*n3, n2, b, k);

c * n1*n2 % n3 = 1; 等价于 c * n1*n2 - 1 = k * n3 ---> c * n1*n2 - k*n3 = 1;求出 c ,exgcd (n1*n2, n3, c, k);

因为扩展的欧几里得求出的值有可能是负数,通过取模的方式得出最小正整数解;比如 a = (a%n3 + n3) % n3;(即求a用k的系数取模,同理求k的最小正整数解就用a的系数取模)

则有 n = (a*n2*n3*p + b*n1*n3*e + c*n1*n2*i) % lcm (n1, n2, n3) ;

还有要注意的是:当求得的ans小于等于起始天数 d 的时候要 + lcm (n1, n2, n3);

 

#include <iostream>

using namespace std;

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

const int Mod = 21252; // lcm (23, 28, 33) 事先求出

int main (void)
{
	int a, b ,c , k, p, e, i, d, cas = 0;
	exgcd (28*33, 23, a, k); a = (a%23+23)%23; 
	exgcd (23*33, 28, b, k); b = (b%28+28)%28;
	exgcd (23*28, 33, c, k); c = (c%33+33)%33;
	while (cin >> p >> e >> i >> d) {
		if (p == -1 && e == -1 && i == -1 && d == -1) break;
		int ans = (a*p*28*33 + b*e*23*33 + c*i*28*23) % Mod;
		ans -= d;
        ans = ans <= 0 ? ans+Mod : ans;  // ans 小于等于天数 d 要+Mod
		cout << "Case " << ++cas << ": the next triple peak occurs in " << ans << " days." << endl;
	}
	return 0;
 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值