实用算法实现-第 27 篇 中国余数定理

本文介绍了中国余数定理,阐述了定理的证明过程,并通过实例分析了如何利用该定理解决实际问题,如计算周期性事件的出现时间。同时,提供了算法实现的思路和步骤,强调了在求解过程中使用欧几里德算法的扩广形式。
摘要由CSDN通过智能技术生成

27.1    中国余数定理

定理:对任意n > 1,如果gcd(a, n) = 1,则方程a • x ≡ 1(mod n)对模n有唯一解,否则方程无解。若方程有解,x可以表示为(a^-1) mod n,x可以由欧几里德算法的扩广形式求出。

设n1, n2, ..., nk两两互质,n = n1• n2 • ... • nk

定义:mi = n1• n2 • ... • ni-1 • ni+1 • ... • nk

定义:ci = mi • (mi^-1 mod ni)

定义:a ≡ (a1•c1 + a2• c2 + ...+ak•ck) (mod n)

可以证明:a ≡ ai (mod ni)

证明如下:

ci = mi • (mi^-1 mod ni) 故此ci ≡ 1 (mod ni)

又由mi ≡ 0 (mod nj)                             j= 1, 2, ..., i-1, i+1, ...k

故此 mi • (mi^-1 mod ni) ≡ 0 (mod nj)        j =1, 2, ..., i-1, i+1, ...k

故此ci ≡ 0 (mod nj)                              j = 1, 2, ...,i-1, i+1, ...k

由  ci ≡ 0 (mod nj)                               j = 1, 2, ..., i-1, i+1, ...k

ci ≡ 1 (mod nj)                               j = i

       可知ci和(0, 0, ..., 0, 1, 0, ..., 0)有一一对应的关系。

故此a ≡ ai • ci                               (mod ni)

≡ ai • mi(mi^-1 mod ni)              (mod ni)

≡ ai                                     (mod ni)

       由上面证明可知:对于两两互质的n1, n2, ..., nk,若已知a1, a2, ..., ak,则可以求出a (mod n),使得ai = a (mod ni)。即a和(a1, a2, ..., ak)一一对应。

由中国余数定理有:

推论:如果n1, n2, ..., nk两两互质,n=n1 • n2 • ... • nk,则对所有整数x和a(i = 1, 2, ..., k), 有x = a(mod ni),当且仅当x = a(mod n)。

27.1.1   实例

PKU JudgeOnline, 1006, Biorhythms.

27.1.2   问题描述

一个人体力、情绪、智力的波动周期为23,28,33天,给定每种状态达到最高点分别为第p, e, i天,从第d天开始,过多少天后会达到三者的最高点。

27.1.3   输入

00 0 0

00 0 100

520 34 325

45 6 7

283102 23 320

203301 203 40

-1 -1 -1 -1

27.1.4   输出

Case1: the next triple peak occurs in 21252 days.

Case2: the next triple peak occurs in 21152 days.

Case3: the next triple peak occurs in 19575 days.

Case4: the next triple peak occurs in 16994 days.

Case5: the next triple peak occurs in 8910 days.

Case6: the next triple peak occurs in 10789 days.

27.1.5   分析

这里23,28,33互质,所以可以用中国剩余定理的这个推论。

先求出mi,再根据欧几里德算法的扩广形式求出((mi^-1) mod ni),再求出ci。将ci作为常数存起来,然后根据公式求出a就可以了。

27.1.6   程序

#include<stdio.h>
int main()
{    intp,e,i,d,a,t=0;
     while(1)
     {
         scanf("%d%d%d%d",&p,&e,&i,&d);
         if(p==-1&& e==-1 && i==-1 && d==-1)
              break;
         a=(5544*p+14421*e+1288*i-d+21252)%21252;
         if(!a)
              a=21252;
         printf("Case%d: the next triple peak occurs in %d days.\n",++t,a);
     }
     return 0;
}

27.2    实例

PKU JudgeOnline, 1006, Biorhythms.

本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值