POJ 1006

首先将题目变成以下方程组,相当于要求这个同余方程的最小解


(n+d)%23 = p;  ->  x%23 = p;  

(n+d)%28 = e;  ->  x%28 = e;  

(n+d)%33 =  i;  ->  x%33 =  i;  


另 M = 23*28*33  M1 = 28*33 M2 = 23*33 M3 = 23*28

若 M1*y1 % 23 = 1;   -> M1*y1*p % 23 =p;

     M2*y2 % 28 = 1;  ->  M2*y2*e % 28 =e;

     M3*y3 % 33 = 1;  ->  M3*y3*i  % 33 =i;


因为 M2 和 M3均为 23 的倍数 ,故( M1*y1*p + M2*y2*e  + M3*y3*i )%23 = p;

因为 M1 和 M3均为 28 的倍数 ,故( M1*y1*p + M2*y2*e  + M3*y3*i )%28 = e;

因为 M1 和 M2均为 33 的倍数 ,故( M1*y1*p + M2*y2*e  + M3*y3*i )%33 = i;


所以 (M1*y1*p + M2*y2*e  + M3*y3*i )是满足这个方程的一个解, 因为 23 38 33 都是素数,所以最小解为  (M1*y1*p + M2*y2*e  + M3*y3*i )% M


y1 y2 y3用代码里面的gcd函数算出,相当于数 x% =z  已知 y、z 求x 的一个过程

数字小一点可以口算,这儿的数字太大了,等以后研究一下


参考: http://www.cnblogs.com/walker01/archive/2010/01/23/1654880.html



#include <iostream>
#include <stdio.h>
#include <math.h>  

using namespace std;
typedef long long LL;  


static const int pCycleDays = 23;
static const int eCycleDays = 28;
static const int iCycleDays = 33;


void gcd(LL a, LL b, LL &d, LL &x, LL &y)  
{  
	if(!b)  
	{  
		d = a, x = 1, y = 0;  
	}  
	else  
	{  
		gcd(b, a %b, d, y, x);  
		y -= x * (a/b);  
	}  
}  
LL inv(LL a, LL n)  
{  
	LL d, x, y;  
	gcd(a,n,d,x,y);  
	return d == 1 ? (x + n) % n : -1;  
}  


int main()
{
	int p,e,i,d;
	int pFix, eFix, iFix;

	int M = pCycleDays*eCycleDays*iCycleDays;
	int M1 = eCycleDays*iCycleDays;
	int M2 = pCycleDays*iCycleDays;
	int M3 = pCycleDays*eCycleDays;

	int t1 = inv(M1,pCycleDays);
	int t2 = inv(M2,eCycleDays);
	int t3 = inv(M3,iCycleDays);

	int count = 0;
	while(cin>>p>>e>>i>>d)
	{
		if(p == -1 && e == -1 && i == -1 && d == -1)
			break;
		count ++;



		int nCommonPeak = (t1*M1*p + t2*M2*e + t3*M3*i - d)%M ;
		if(nCommonPeak <= 0)
			nCommonPeak += M;


		char trace[200];
		sprintf(trace,"Case %d: the next triple peak occurs in %d days.",count,nCommonPeak);
		printf("%s\n",trace);
	}


	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值