生理周期[PKU1006]

生理周期
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 132195   Accepted: 42171

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

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

采用以下格式: 
Case 1: the next triple peak occurs in 1234 days. 

注意:即使结果是1天,也使用复数形式“days”。

Sample Input

0 0 0 0
0 0 0 100
5 20 34 325
4 5 6 7
283 102 23 320
203 301 203 40
-1 -1 -1 -1

Sample Output

Case 1: the next triple peak occurs in 21252 days.
Case 2: the next triple peak occurs in 21152 days.
Case 3: the next triple peak occurs in 19575 days.
Case 4: the next triple peak occurs in 16994 days.
Case 5: the next triple peak occurs in 8910 days.
Case 6: the next triple peak occurs in 10789 days.

可以很简单,直接数50000个就行。也可以更一般的用线性同余方程组。
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
class Congruent_Linear_Equation_Group {
private:
#define MAX_GROUP_SIZE 10
    int groupSize, dis;
    int A[MAX_GROUP_SIZE], M[MAX_GROUP_SIZE];
    int gcd(int a, int b) {
        int k;
        while (b != 0) {
            k = b;
            b = a % b;
            a = k;
        }
        return a;
    }
    /* * * * * * * * * *
     * a,b=>x,y        *
     * ax+by=gcd(a,b)  *
     * * * * * * * * * */
    int extended_gcd(int a, int b, int &x, int &y) {
        int ans, t;
        if (b == 0) {
            x = 1;
            y = 0;
            return a;
        } else {
            ans = extended_gcd(b, a % b, x, y);
            t = x;
            x = y;
            y = t - (a / b) * y;
        }
        return ans;
    }
public:
    Congruent_Linear_Equation_Group() {
        groupSize = 0;
    }
    void clear() {
        groupSize = 0;
    }
    void addEquation(int a, int m) {
        if (m == 0) {
            return;
        }
        A[groupSize] = a;
        M[groupSize++] = m;
    }
    int getSolution() {
        int at = A[0], mt = M[0], ap, mp, x, y, z;
        for (int i = 1; i < groupSize; i++) {
            ap = A[i];
            mp = M[i];
            if ((at - ap) % gcd(mt, mp) != 0) {
                return -1;
            }
            /* * * * * * * * * * * * *
             *  x=mt*y+at            *
             *  x=mp*z+ap            *
             *    => at-ap=mp*z-mt*y *
             * * * * * * * * * * * * */
            extended_gcd(mp, -1 * mt, z, y);
            //  => mp*z-mt*y=gcd(mp,-mt)
            z = z * (at - ap) / gcd(mp, -mt);
            x = mp * z + ap;
            mt = mt * mp / gcd(mt, mp);
            while (x <= 0) {
                x += mt;
            }
            at = x;
        }
        dis = mt;
        return x;
    }
    int getNextSolution(int x) {
        return x + dis;
    }
};
Congruent_Linear_Equation_Group cc;
int main() {
    int a, b, c, d, i = 0;
    while (scanf("%d%d%d%d", &a, &b, &c, &d) != EOF) {
        if (a == -1 && b == -1 && c == -1 && d == -1) {
            break;
        }
        i++;
        cc.clear();
        a %= 23;
        b %= 28;
        c %= 33;
        cc.addEquation(a, 23);
        cc.addEquation(b, 28);
        cc.addEquation(c, 33);
        int x = cc.getSolution();
        if (x <= d) {
            x += 21252;
        }
        while (x-21252>d) x-=21252;
        printf("Case %d: the next triple peak occurs in %d days.
", i, x - d);
    }
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/dramstadt/p/6186611.html