您的位置:首页 > 其它

poj 1006 生理周期 中国剩余定理

2017-07-14 22:09 337 查看
题意:人的身体素质,情绪状况,智力水平是在不断波动。时高时低。它们的周期分别是23,28,33天,顶峰会出现在周期中。给定p,e,i分别代表起三种水平从当年到达高峰的天数。对于每个周期,会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数(d),输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。求最少天数。

poj 1006 :http://poj.org/problem?id=1006&lang=zh-CN&change=true

思路:假设在第x天同时达到顶峰。

x=p+k1*m0;

x=e+k2*m1;

x=I+k3*m2;

k1,k2,k3为整数.

化为同余方程组

p=x%m0;

e=x%m1;

I=x%m2;

mi为给定的周期,均为质数,可以用中国剩余定理求x。x还要减去起始位置d才是答案

#include<cstdio>
#define ll long long
using namespace std;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
x=1;
y=0;
d=a;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
ll inv(ll a,ll p)//求a关于模p的逆元
{
ll x,y,d;
exgcd(a,p,d,x,y);
x=((x%p)+p)%p;
return x;
}
ll china(int n,ll *a,ll *m)
{
ll ret=0;
ll M=1;
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,e,i,d;
int cas=0;
while(~scanf("%lld%lld%lld%lld",&p,&e,&i,&d))
{
ll a[3],m[3];
if(p==-1&&e==-1&&i==-1&&d==-1)break;
m[0]=23;m[1]=28;m[2]=33;
a[0]=p;a[1]=e;a[2]=i;
ll ans=china(3,a,m);
ll
4000
MOD=m[0]*m[1]*m[2];
ans=((ans-d)%MOD+MOD)%MOD;
printf("Case %d: the next triple peak occurs in %lld days.\n",++cas,ans?ans:MOD);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: