中国剩余定理
孙子算经里有这样一个问题:“今有物不知其数。三三数之剩二。五五数之剩三,七七数之剩二,问物几何?”
翻译成如今的数学问题就是 x%3 == 2,x%5 == 3,x%7 == 2,求x 的值;
遇到这这样一个问题非常多C语言刚開始学习的人不禁会想到用暴力能够算出来。还要这样一个定理干嘛?
假设数据相当大呢?计算机就会计算相当困难。然而这个问题早早的就被孙子攻克了。
求出3,5,7 两两中的最小公倍数lcm,k*lcm与还有一个数mod等于1(找出一个符合条件的k);
用k*lcm*还有一个没有在lcm中的数的等式的余数 [(有点绕)就是 lcm(3,5),还有一个数就是7 在x%7==2 的等式中的余数 就是2 即找出这k*lcm(3,5)*2]
求法(剩余定理思想):
Lcm(3,5) = 15; // lcm是最小公倍数
Lcm(3,7) = 21;
Lcm(5,7) = 35;
a*15%7 == 1;
b*21%5 == 1;
c*35%3 == 1;
可求得a,b,c的值为1,1,2;
我们可得15%7 == 1 , 21%5 == 1 , 70%3 == 1;
Ans = (15*2 + 21*3 + 70*2) % lcm(3,5,7);
Ans = 23;
再加一个例题:
一个数被3除余1,被4除余2。被5除余4,这个数最小是几?
题中3、4、5三个数两两互质。
则〔4。5〕=20。〔3,5〕=15;〔3,4〕=12;〔3,4,5〕=60。
为了使20被3除余1。用20×2=40; 使15被4除余1。用15×3=45; 使12被5除余1,用12×3=36。
然后,40×1+45×2+36×4=274。
由于,274>60;
所以。274%60 = 34。就是所求的数。
粘个剩余定理题 POJ 1006 http://poj.org/problem?
id=1006
题目又上角有中文意思
这道题的解法就是:
已知(ans+d)%23=a; (ans+d)%28=b; (ans+d)%33=c
使33×28×X被23除余1。用33×28×8 = 5544;
使23×33×Y被28除余1,用23×33×19 = 14421;
使23×28×Z被33除余1。用23×28×2 = 1288。
于是X==8, Y==19, Z==2;
因此有(5544×a + 14421×b + 1288×c)% lcm(23,28,33) =ans + d
又23、28、33互质,即lcm(23,28,33) = 21252;
所以有ans =(5544×a+14421×b+1288×c-d)% 21252
AC代码
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int a, b, c, d,cnt=1;
int ans;
while (scanf("%d%d%d%d", &a, &b, &c, &d)!=EOF&&a!=-1)
{
ans = (a * 5544 + b * 14421 + c * 1288) % 21252;
ans -= d;
if (ans<=0) ans += 21252;
if(ans>21252) ans=21252;
printf("Case %d: the next triple peak occurs in %d days.\n", cnt++, ans);
}
return 0;
}
这个题暴力也能过
暴力AC代码
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int a, b, c, d,cnt=1,i;
while (scanf("%d%d%d%d", &a, &b, &c, &d)!=EOF&&a!=-1)
{
for(i=1; ; i++)
if((i-a)%23==0&&(i-b)%28==0&&(i-c)%33==0&&i>d)
{
break;
}
printf("Case %d: the next triple peak occurs in %d days.\n", cnt++, i-d);
}
return 0;
}