中国剩余定理应用 (poj 1006 Biorhythms)

版权声明:低调地前行,越努力越幸运! https://blog.csdn.net/SSYITwin/article/details/83312964

Biorhythms

1.中国剩余定理回顾:

   这个问题源自于我国数学古书《孙子算经》中的一道问题:“今有物,不知其数,三三数之,剩二;五五数之,剩三;七七数之,剩二。问物几何?”意思是一个整数除以三余二,除以五余三,除以七余二,求这个整数(满足条件且最小)。

做法是:

   n%3==2,n%5==3,n%7==2,并且3,5,7折三个数是互质的。

   我们找到使(5*7*a)%3==1的数:(5*7*a)=70;

   我们找到使(3*7*b)%5==1的数:(5*7*b)=21;

   我们找到使(3*5*c)%7==1的数:(3*5*c)=15

  那么(70×2+21×3+15×2) % (3×5×7) = 23, 23即是答案。

理解如下:

   70×2 = 140,当中的2是指n%3 = 2的2,因为70%3=1,乘2后使其能满足%3=2的条件。(毕竟题目要求的是%3==2的,而不是%3==1的,但是我们可以在求得%3==1得基础上扩大倍数,求得%3==2的)

  同理, 21×3使其能满足%5=3,15×2使其能满足%7=2 又70能整除5和7,21能整除3和7,15能整除3和5 因此70×2+21×3+15×2 = 233能满足%3=2,%5=3,%7=2的条件 将233对3×5×7=105取模,是为了取得最小的情况,因为105是能够同时整除3,5,7的数,如果减去,对该数满足%3=2,%5=3,%7=2没有影响。因此对105取模,得到的结果便是最小并满足条件的数。

     这里的中国剩余定理必须要求除数是互质的,但是有些题目的同余方程式除数并不互质,那么将不能使用传统的中国剩余定理。

2.题意:

    人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。

3.解析:

  找到使(23×28)的公倍数模33得1的数,答案是1288

  找到使(23×33)的公倍数模28得1的数,答案是14421|

  找到使(28×33)的公倍数模23得1的数,答案是5544

      (5544×p+14421×e+1288×i) % (23×28×33) = ans + d

4.代码:

#include <iostream>
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int md[3]={23,28,33};
int re[3];
int d;
int exgcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
		
	}
	int ans=exgcd(b,a%b,x,y);
	int temp=x;
	x=y;
	y=temp-(a/b)*y;
	return ans;
	  
}
int China_Remainder(int md[],int re[])
{
	int lcm=1;
	int d,x,y,m,sum=0;
	for(int i=0;i<3;i++)
	   lcm=lcm*md[i];
	for(int i=0;i<3;i++)
	{
		m=lcm/md[i];
		d=exgcd(md[i],m,x,y);
		sum=(sum+y*m*re[i])%lcm;
	}
	return (lcm+sum%lcm)%lcm;
}
int main()
{
	int cnt=1;
	while(~scanf("%d%d%d%d",&re[0],&re[1],&re[2],&d))
	{
		if(re[0]==-1||re[1]==-1||re[2]==-1||d==-1)
		   break;
		int num=China_Remainder(md,re);
		if(num==0) num=21252;
		else if(num<0)
		  num=num+21252;
		printf("Case %d: the next triple peak occurs in %d days.\n",cnt++,num-d);
	}
	return 0;
}

一开始就套用的中国剩余定理的模板,结果WA。 AC代码如下:

#include <iostream>
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int md[3]={23,28,33};
int re[3];
int main()
{
	int p,e,i,d;
	int cnt=1;
	while(~scanf("%d%d%d%d",&p,&e,&i,&d))
	{
		if(p==-1||e==-1||i==-1||d==-1)
		  break;
		int lcm=21252;
		int num=(5544*p+14421*e+1288*i-d+21252)%21252;
		if(num==0)
		   num=21252;
		printf("Case %d: the next triple peak occurs in %d days.\n",cnt++,num);
	}
}

5.参考

猜你喜欢

转载自blog.csdn.net/SSYITwin/article/details/83312964