Poj1006-中国剩余定理

题意:

  这题的目的是找到在三个循环周期内找到重合的天。

  首先给定三个生理周期的出现的某一天,这样很自然能得到高峰是一个单独周期的第几个天。

  

p = p % 23;
e = e % 28;
i = i % 33;

我们假设是第S天满足要求,那么S必然满足以下方程式:

  S = p + 23k1 = e + 28k2 = i + 33k3  (k1, k2, k3 均 ≥ 0, 且为正整数)

我们若是想要直接求出k1, k2, k3不太现实,我们可以由结果逆推:

S % 23 = p;
S % 28 = e;
S % 33 = i;

我们现在假设三个数n1, n2, n3,这三个数分别满足:

n1 % 23 = p;
n2 % 28 = e;
n3 % 33 = i;

我们的目标就是找到n1,n2,n3这三个数,使得 S = n1 + n2 + n3 满足  S = p + 23k1 = e + 28k2 = i + 33k3  (k1, k2, k3 均 ≥ 0, 且为正整数)

由数学公式:如果 a % b = c , 则有  (a + kb ) % b = c

例如由(n1 + n2 + n3) % 23 = p ==>(n2 + n3) % 23 = p ==> n2 % 23 = p, n3 % 23 = p, 即:

n1 % 23 = p且n2, n3为23的倍数。

进而对n1,n2,n3三种情况按照上述讨论,得到:

①n1 % 23 = p且n2, n3为23的倍数。
②n2 % 28 = e且n1, n3为28的倍数。
③n3 % 33 = i且n1, n2为33的倍数。

再进一步推导:

①n1 % 23 = p且为28、33的倍数。
②n2 % 28 = e且为23、33的倍数。
③n3 % 33 = i且为23、28的倍数。

到了现在,我们就能求出n1, n2, n3了,但是,还有一个小细节在这个地方,以①为例,我们并不是从所有的28,33的公倍数中找出%23 = p的数,而是先找出%23 = 1的数,再乘上k倍即可。

运用的数学公式为a%b=c,那么 (a*k)%b=kc

在最后,我们还是不能够保证我们算得的n1 + n2 + n3是满足条件的最小值,只需要通过%23,28,33的最小公倍数即可,理由还是,如果 a % b = c , 则有  (a + kb ) % b = c。

AC代码

#include <iostream>
using namespace std;

int gcd(int a, int b)
{
   return b == 0 ? a : gcd(b, a % b);
}

int lcm(int a, int b)
{
   return a / gcd(a, b) * b;
}

int main()
{
   ios::sync_with_stdio(false);
   int a, b, c, d, sum = 0;
   while(cin >> a >> b >> c >> d && a != -1)
   {
      sum++;
      a = a % 23; b = b % 28; c = c % 33;
      int n1, n2, n3;
      int flag1 = 1, flag2 = 1, flag3 = 1;
      int s1 = lcm(28, 33), s2 = lcm(23, 33), s3 = lcm(23, 28);
      for(int k = 1; flag1 || flag2 || flag3; k++)
      {
         if(flag1 && k * s1 % 23 == a)
         {
            flag1 = 0;  n1 = k * s1;
         }
         if(flag2 && k * s2 % 28 == b)
         {
            flag2 = 0;  n2 = k * s2;
         }
         if(flag3 && k * s3 % 33 == c)
         {
            flag3 = 0;  n3 = k * s3;
         }
      }
      int s = (n1 + n2 + n3) % 21252;
      if(s == 0)  s = 21252;
      if(s - d < 0)  s += 21252;
      cout << "Case "<< sum << ": the next triple peak occurs in " << s - d << " days." << endl;
   }
   return 0;
}

 

posted @ 2020-08-31 14:31  ACM-Epoch  阅读(182)  评论(0编辑  收藏  举报