中国剩余定理

  写完扩展欧几里得就要顺便写一下中国剩余定理。

  首先,什么是中国剩余定理:中国最早提出来的,又名孙子定理的一个求一次同余方程组的方法。

  

   对,就长上面这个样子(这是百度百科复制的图片)。看起来很复杂,那要怎么求解呢?

  中国剩余定理的最早版本是有所有m互质的前提的,所以就来讲一讲如何处理互质的情况。

  令N[i]能被m[1]、m[2]、...、m[i-1]、m[i+1]、...、m[n]整除,但除m[i]后余1.

  令M为数组m的最小公倍数。

  那么x=Σ(N[i]*a[i])+t*M为所有解,t为整数。

  此时我们就得到了解。但是,N数组怎么求呢?

  设x为一个数,y为一个数

  N[i]能被m[1]、m[2]、...、m[i-1]、m[i+1]、...、m[n]整除,所以N[i]=M/m[i]*x

  N[i]除m[i]后余1,所以N[i]=m[i]*y+1

  联立以上两方程,可以得到,M/m[i]*x-m[i]*y=1,这个方程用扩展欧几里得很容易可以得到一组解。

  得到解后就可以得到N[i]了,最后注意细节就好了。

 

  HDU 1370为模板题。

 

#include <cstdio>
#define FOR(i, x, y) for(int i = x; i <= y; ++i)
int t, n, k, ans, M, day, a[20], m[20];
int e_gcd(int a, int b, int &x, int &y)//参数可为负数的扩展欧几里德定理
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int ans = e_gcd(b, a%b, x, y);
    int temp = x;
    if(a * b < 0)
    {
        x = -y;
        y = a / b * y - temp;
    }else
    {
        x = y;
        y = temp - a / b * y;
    }
    return ans;
}
int CRT(int a[], int m[], int k)//Chinese Remainder theory
{
    int ans = 0;
    M = 1;//最小公倍数
    FOR(i, 0, k-1) M *= m[i];
    FOR(i, 0, k-1)
    {
        int x, y, temp = M / m[i];
        e_gcd(temp, m[i], x, y);
        ans = (ans + a[i] * temp * x) % M;
    }
    return (ans % M + M) % M;
}
int main()
{
    scanf("%d", &t);
    while(t--)
    {
        FOR(i, 1,100000)
        {
            m[0] = 23; m[1] = 28; m[2] = 33;
            FOR(j, 0, 2) scanf("%d", &a[j]);
            if(a[0] == -1) break;
            scanf("%d", &day);
            ans = CRT(a, m, 3);
            while(ans <= day) ans += M;
            printf("Case %d: the next triple peak occurs in %d days.\n", i, ans-day);
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/cons/p/5403832.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值