【中国剩余定理】POJ 1006 生理周期

本文详细解释了中国剩余定理(孙子定理),包括其数学原理、使用条件和算法描述,并通过实例演示了如何求解相关问题。重点介绍了如何使用扩展欧几里得算法来寻找解,并提供了编程实现的示例。
[url]http://poj.org/problem?id=1006&lang=zh-CN&change=true[/url]

[size=medium][color=blue]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.[/color]

[b][color=green]中国剩余定理【孙子定理】详解:[/color][/b]

其实就是解方程组:
[img]http://dl.iteye.com/upload/attachment/518037/08953bd2-d392-30b9-a7ae-20c9be8d9355.png[/img]
求res的值
[color=red][b]使用中国剩余定理的条件【重要!!!】:
n1,n2,n3……ni 这些数两两互质(互素)!!也就是两两之间的最大公约数是1!![/b][/color]

回到正题:先看一下这个视频,后面的会更好理解!
[url]http://v.youku.com/v_show/id_XMTExNTAzOTIw.html[/url]

算法描述:【利用同余的加性和乘性】
令nn = n1×n2×n3×……×ni;
那么也就是说nn是ni的倍数!
所以有:nn/ni是其他n的倍数,不是ni的倍数,[color=red]而且nn/ni跟ni没有大于1的公约数[/color]
【如nn/n2,是n1,n3,n4...的倍数,但不是n2的倍数,[color=red]而且nn/n2和n2的最大公约数是1[/color],因为上面说了这些数[color=red]两两互质[/color]】
[color=red]既然nn/ni是其他n的倍数,那么nn/ni这个数模其他n【n1,n2...n[i-1],n[i+1]...】的结果肯定是0,为下面利用同余的加性奠定了基础[/color]

[color=green]所以根据视频那种方法
可以先找到x使得:
[img]http://dl.iteye.com/upload/attachment/518039/3d2acea8-57ec-3889-8f5e-eec52d5df32b.png[/img]
假设找到这个x了,那么要满足第i个方程,则利用同余的乘性必有:
[img]http://dl.iteye.com/upload/attachment/518041/b37110ea-3547-35c9-9857-76a36bc3a945.png[/img]
那么[img]http://dl.iteye.com/upload/attachment/518045/3270ddf4-c31e-3bc8-944b-a8e1f591b0fc.png[/img]就是res的一部分,它使得res满足第i个方程
所以利用同余的加性,把满足所有方程的这么一个部分加起来就是求出来的其中一组解了[/color]

[color=blue]怎么找x呢?【关键】
∵有重要条件:两两互质
∴nn/ni和ni也互质
∴[img]http://dl.iteye.com/upload/attachment/518053/7e6150ef-8a5e-3253-af52-0609b4f5109e.png[/img]【根据上述:使用中国剩余定理的条件】
∴由扩展的【欧几里得】得:
[img]http://dl.iteye.com/upload/attachment/518055/9ce16480-1fae-30d3-852c-ccaed708360b.png[/img]
∴两边同时模ni得:
[img]http://dl.iteye.com/upload/attachment/518051/089c7610-d60e-32d4-961f-76f3bde6cef6.png[/img]
跟上面的式子[img]http://dl.iteye.com/upload/attachment/518039/3d2acea8-57ec-3889-8f5e-eec52d5df32b.png[/img]对比,发现x = x0
x0怎么求?
不就是利用【扩展欧几里得定理】咯!

[/color]
另外推荐题目:[url]http://acm.hdu.edu.cn/showproblem.php?pid=1930[/url]
[/size]


#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <set>
//#include <map>
#include <queue>
#include <utility>
#include <iomanip>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <ctype.h>
using namespace std;

void Egcd (int a, int b, int &x, int &y) //扩展欧几里得【无返回版】求x
{
if (b == 0)
{
x = 1, y = 0;
return ;
}
Egcd (b, a%b, x, y);
int tp = x;
x = y;
y = tp - a/b*y;
}
int CRT (int n[], int b[], int nn)
{
int res = 0, x, y, i;
for (i = 0; i < 3; i++)
{
int a = nn / n[i];
Egcd (a, n[i], x, y); //求x
res += a * x * b[i]; //把所有组成部分加起来【加性】
} //其中*b[i]是利用了同余的乘性
return res;
}
int main()
{
int n[5] = {23, 28, 33}, b[5], i, date, k = 1, x0;
while (1)
{
for (i = 0; i < 3; i++)
scanf ("%d", b+i);
scanf ("%d", &date);
if (date == -1)
break;
x0 = (CRT (n, b, 21252) - date) % 21252; //使解不大于21252
if (x0 <= 0)
x0 += 21252; //负数或0特殊考虑
printf ("Case %d: the next triple peak occurs in %d days.\n", k++, x0);
}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值