PKU1006 Biorhythms

问题链接:PKU1006

本题可以直接用中国剩余定理来解,同余方程如下:

X≡p(mod 23)

X≡e(mod 28)

X≡i(mod 33)

其中,23、28和33是两两互素的,满足中国剩余定理的前提条件。

#include <stdio.h>

// 递推法实现扩展欧几里德算法
long exgcd(long a, long b, long  *x, long *y)
{
    long x0=1, y0=0, x1=0, y1=1;
    long r, q;
    *x=0;
    *y=1;

    r = a % b;
    q = (a - r) / b;
    while(r)
    {
        *x = x0 - q * x1;
        *y = y0 - q * y1;
        x0 = x1;
        y0 = y1;
        x1 = *x;
        y1 = *y;

        a = b;
        b = r;
        r = a % b;
        q = (a - r) / b;
    }
    return b;
}

// 扩展欧几里德算法求逆元
long minv(long a, long p)
{
    long x, y;

    exgcd(a, p, &x, &y);

    return x<0 ? x+p : x;
}

// 中国剩余定理(Chinese remainder theorem, CRT)
long crt(long a[], long m[], int n)
{
    long bm=1, subm[n], x=0;
    int i;

    for(i=0; i<n; i++)
        bm *= m[i];
    for(i=0; i<n; i++)
        subm[i] = bm / m[i];
    for(i=0; i<n; i++) {
        x += subm[i] * minv(subm[i], m[i]) * a[i];
        x %= bm;
    }

    return x;
}

int main(void)
{
    long p, e, i, d;
    long a[3], m[3];
    long x, bm;
    int ncase = 1;
    for(;;) {
        scanf("%ld%ld%ld%ld", &p, &e, &i, &d);
        if(p==-1 && e==-1 && i==-1 && d==-1)
            break;
        a[0] = p;
        a[1] = e;
        a[2] = i;
        m[0] = 23;
        m[1] = 28;
        m[2] = 33;

        bm = 23 * 28 * 33;
        x = crt(a, m, 3);
        while(x<=d)
            x += bm;

        printf("Case %d: the next triple peak occurs in %ld days.\n", ncase++, x-d);
    }

    return 0;
}


你可能感兴趣的:(数论,ACM-ICPC,同余方程)