zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    乐乎环球WiFi
    Freeswitch 添加可转码的G729编码
    freeswitch 使用mysql替换默认的sqlite
    IDEA项目突然提示找不到符号或程序包不存在
    JAVA_四大代码块_普通代码块、构造代码块、静态代码块、同步代码块。
    动态规划_连续子数组的最大和
    电话号码分身
    ajax中用jsonp接收json数据
    用Navicat建表的字段编码问题
    阿里云ubuntu安装jdk8+mysql+tomcat
  • 原文地址:https://www.cnblogs.com/ACM-Epoch/p/13589382.html
Copyright © 2011-2022 走看看