中国剩余定理

中国剩余定理

维基百科,自由的百科全书
 
跳转到: 导航, 搜索

中国剩余定理Chinese Remainder Theorem中国余数定理),古有“韩信点兵”、“孙子定理”、“鬼谷算”、“隔墙算”、“剪管术”、“秦王暗点兵”、“物不知数”之名,是数论中的一个重要命题。

目录

[隐藏]

[编辑] 物不知数

在中国古代著名数学著作《孙子算经》中,有一道题目叫做“物不知数”,原文如下:

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。

中国数学家秦九韶1247年做出了完整的解答,口诀如下

三人同行七十希,五树梅花廿一支,七子团圆正半月,除百零五便得知

这个解法实际上是,首先利用秦九韶发明的大衍求一术求出5和7的最小公倍数35的倍数中除以3余数为1的最小一个70(这个称为35相对于3的数论倒数),3和7的最小公倍数21相对于5的数论倒数21,3和5的最小公倍数15相对于7的数论倒数15。然后

233便是可能的解之一。它加减3、5、7的最小公倍数105的若干倍仍然是解,因此最小的解为233除以105的余数23。

附注:这个解法并非最简,因为实际上35就符合除3余2的特性,所以最小解是: 最小解加上105的正整数倍都是解。

[编辑] 形式描述

以上解法若推广到一般情况,便得到了中国剩余定理的一个构造性证明。

一般地,中国剩余定理是指若有一些两两互质整数 ,则对任意的整数:a1,a2,...an,以下联立同余方程组对模 有公解:

[编辑] 克罗内克符号

为了便于表述,对任意的正整数用一个常用函数ζi,j表示,称之为克罗内克符号(Kronecker).定义:

使用该符号,即可给出上述一般同余方程组的求解过程,分两步完成

  • 对每个,先求出正整数bi满足,即所求的bi满足条件:,但被每个整除。其求法如下:记,根据条件两两互素,可知rimi也互素,故存在整数cidi使得rici + midi = 1.令bi = rici,则对每个,相对应的mj显然整除bi,并且。由此表明bi即为所求。
  • 对于前述所求的bi,令,则,这说明x0为上述同余方程组的一个解,从而所有的解可表示为,其中的n可以取遍所有的整数。

[编辑] 近世交换环及推广

设为有单位元交换环,为环的理想,并且当时,,则有典范的环同构,其中环同构由映射)给出。

模板

 1 ll x,y;

 2  ll ext_eulid(ll a,ll b)

 3  {

 4      int t,d;

 5      if(b == 0)

 6      {

 7          x = 1;

 8          y = 0;

 9          return a;

10      }

11      d = ext_eulid(b,a%b);

12      t = x;

13      x = y;

14      y = t - (a/b)*y;

15      return d;

16  }

17  ll CRT(ll *p,ll *o,int num)//p数组代表余数,o数组代表互质的数

18  {

19      int i;

20      ll ans = 0,n = 1;

21      for(i = 1;i <= num;i ++)

22      {

23          n *= o[i];

24      }

25      for(i = 1;i <= num;i ++)

26      {

27          ext_eulid(n/o[i],o[i]);

28          x = (x+o[i])%o[i];

29          ans = (ans + n/o[i]*p[i]*x) % n;

30      }

31      return ans;

32  }

 http://poj.org/problem?id=1006

未用模板解法 求解基础数

View Code
 1 #include <iostream>

 2 #include<cstdio>

 3 #include<string.h>

 4 using namespace std;

 5 int base(int x,int a,int p)

 6 {

 7     int i;

 8     int y = a;

 9     if((a%x!=0&&p%x==0)||(a%x==0&&p%x!=0))

10     return 0;

11     if(a%x!=p%x)

12     {

13         for(i = 1; ;i++)

14         {

15             a = y*i;

16             if(a%x==p%x)

17             break;

18         }

19     }

20     return a;

21 }

22 int main()

23 {

24     int p,e,i,d,j,k = 0;

25     int y = 21252;

26     int a = y/23;

27     int b = y/28;

28     int c = y/33;

29     while(cin>>p>>e>>i>>d)

30     {

31         k++;

32         if(p==-1&&e==-1&&i==-1&&d==-1)

33         break;

34         int a1 = base(23,a,p);

35         int b1 = base(28,b,e);

36         int c1 = base(33,c,i);

37         int s = a1+b1+c1;

38         printf("Case %d: ",k);

39         if(s%y==0)

40         s=y;

41         else

42         {

43             s = s%y;

44             if(s<=d)

45             s+=y;

46         }

47         printf("the next triple peak occurs in %d days.\n",s-d);

48     }

49     return 0;

50 }

 套模板

View Code
 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<cmath>

 5 using namespace std;

 6 int x,y,s;

 7 int exgcd(int a,int b)

 8 {

 9     if(b==0)

10     {

11         x = 1;

12         y = 0;

13         return a;

14     }

15     int egcd = exgcd(b,a%b);

16     int temp;

17     temp = x;

18     x = y;

19     y = temp - (a/b)*y;

20     return egcd;

21 }

22 int crt(int *p,int *o)

23 {

24     int i;

25     int ans  =0;

26     for(i = 1; i <= 3 ; i++)

27     {

28         exgcd(s/o[i],o[i]);

29         x = (x+o[i])%o[i];

30         ans = (ans+s/o[i]*p[i]*x)%s;

31     }

32     return ans;

33 }

34 int main()

35 {

36     int p,e,i,d,k = 0,o[10] = {0,23,28,33},w[10],ans;

37     s = 21252;

38     while(cin>>p>>e>>i>>d)

39     {

40         if(p==-1&&e==-1&&i==-1&&d==-1)

41         break;

42         int ans = 0;

43         k++;

44         w[1] = p;

45         w[2] = e;

46         w[3] = i;

47         ans = crt(w,o)-d;

48         if(ans<=0)

49         ans+=s;

50         printf("Case %d: ",k);

51         printf("the next triple peak occurs in %d days.\n",ans);

52     }

53     return 0;

54 }

 

你可能感兴趣的:(中国剩余定理)