zoukankan      html  css  js  c++  java
  • Poj 1006 生理周期(中国剩余定理)


    一、Description

    人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为10,下次出现三个高峰同天的时间是12,则输出2(注意这里不是3)。

    Input

    输入四个整数:p, e, i和d。 p, e, i分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。d 是给定的时间,可能小于p, e, 或 i。 所有给定时间是非负的并且小于365, 所求的时间小于21252。
    当p = e = i = d = -1时,输入数据结束。

    Output

    从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。

    二、问题分析
            发现这道题有翻译的时候,长舒了一口气。但没想到中文意思都这么坑爹,唉,硬着头皮看了几遍没思路,后来看了discuss发现是中国余数定理(其实我根本不懂神马中国余数定理)。这就是这道题的全部了,下面详细了解一下这个定理。
    中国古代求解一次同余式组(见同余)的方法。是数论中一个重要定理。又称中国剩余定理。
    设m1,m2,…mk是两两互素的正整数,则对任意b1,b2,…,bk,同余方程组
    x mod m1=b1 mod m1,
    x mod m2=b2 mod m2,

    x mod mk=bk mod mk, 其解为:
     x=(M1’M1b1+M2’M2b2+…+M’kMkbk )mod m
    m=m1m2…mk,   
    Mi=m/mi  
    MiMi’ mod mi=1 显然(Mi,mi)=1

    解题思路:

    令某数为M,令素数为A,B,C,D,…,Z,已知M/A余a,M/B余b,M/C余c,M/D余d,…,M/Z余z。求M=?

    因为A,B,C,D,…,Z为不同的素数,故,B*C*D*…*Z不可能被A整除,有等差数列(B*C*D*…*Z)+(B*C*D*…*Z)N中取A个连续项,这A个连续项分别除以A的余数必然存在0,1,2,3,…,A-1,所以,从这A个连续项中能寻找到除以A余1的数。再用除以A余1的这个数*a其积必然除以A余a,这个除以A余a的数,为能够被素数B*C*D*…*Z整除的数,为第一个数;

    再按同样的道理,从A*C*D*…*Z的倍数中寻找除以B余b的数,该数具备被素数A,C,D,…,Z整除的特性,为第二个数;

    因为,第一个数除以A余a,第二个数能被素数A,C,D,…,Z整除,即能被A整除,所以,第一个数+第二个数之和,仍然保持除以A余a;

    同理,第二个数除以B余b,因第一个数能被B整除,所以,第二个数+第一个数之和,仍然保持除以B余b。即,第一个数+第二个数之和,为满足除以A余a,除以B余b。

    依此类推,按上面的方法寻找到除以各素因子的余数的数之总和,为满足除以各素因子余数的条件的数。总和再减去能被这几个素数共同整除的数(A*B*C*D*…*Z)N后,其差仍然保持除以各素因子余数的条件的数。由此构成孙子定理的解法。
    例题:
       x mod 3=2
       x mod 5=3
       x mod 7=2
    m1=3 m2=5 m3=7  b1=2 b2=3 b3=2
    m=m1*m2*m3=3*5*7
    M1=m/m1=5*7  M1’=Mi(mi)-1mod mi=2
    M2=m/m2=3*7  M2’=Mi(mi)-1mod mi=1
    M3=m/m3=3*5  M3’=Mi(mi)-1mod mi=1
    x=(M1’M1b1+M2’M2b2+…+M’kMkbk )mod m
    =(2*5*7*2+1*3*7*3+1*3*5*2)mod 105
    =(140+63+30) mod 105=233 mod 105=23

    三、问题解决

          有了上面的普及,可以得到我们要的式子:Days=(5544*p+14421*i+1288*e)%21252.看到输入数据的0,应该是代表第一天的意思吧,有点难以理解。

    import java.util.Scanner;
    public class N1006_Biorhythms{
    	
        public static void main(String args[]){
        	Scanner cin=new Scanner(System.in);
        	int num=0;
        	while(cin.hasNext()){
        		int p =cin.nextInt();
        		int e =cin.nextInt();
        		int i =cin.nextInt();
        		int d =cin.nextInt();
        		if(p==-1 && e==-1 && i==-1 && d==-1){
        			break;
        		}
        		num++;
        		int days=(5544 * p + 14421 * e + 1288 * i) % 21252 -d;
        		if(days <= 0){
        			days+=21252;
        		}
        		System.out.println("Case "+num+": the next triple peak occurs in "+days+" days.");
        	}
        }
    }
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    pip安装不成功的解决办法
    nginx常用的请求头参数和防DDOS攻击
    nginx报错:‘open too many files’解决
    nginx根据http_user_agent来拦截访问
    centos7安装logstash
    aws创建实例ec2时关联IAM
    docker清理多余的镜像和stop的容器
    理想
    +: indexed part-select
    Features Download Pricing Mind Maps Blog XMind的快捷键
  • 原文地址:https://www.cnblogs.com/AndyDai/p/4734212.html
Copyright © 2011-2022 走看看