中国剩余定理(c语言)

孙子定理是中国古代求解一次同余式组(见同余)的方法。是数论中一个重要定理。又称中国余数定理。一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作《孙子算经》卷下第二十六题,叫做“物不知数”问题,原文如下:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。

定理:
在这里插入图片描述
例子:在这里插入图片描述
c代码:

/*中国剩余定理
输入一个n,表示同余式组的同余式的个数
然后依次输入 b[1],...,b[n](即上面的a[i])
以及m[1],...,m[n]
计算 mm=m[1]*...*m[n]
计算M[1] =mm/m[1]...M[n]=mm/m[n];
求M[i]模m[i]的逆元:ni[i]=NI(M[i],m[i]) 
 最后计算x≡ ( ni[1]*M[1]*b[1]+...+ni[n]*M[n]*b[n] )% mm
*/



/*
4
1 5 4 10
5 6 7 11


结果: 
x ≡ 2111 (mod 2310)

*/
#include<stdio.h>

int NI(int a,int m);

int main()
{
	printf("-------------<中国剩余定理求同余式组的解 >------------------hao--\n\n");
	printf("\n说明:\n第一行输入同余式组的同余式的个数n(<20)\n");
	printf("第二行依次输入n个b[i]的值\n");
	printf("第三行依次输入n个m[i]的值\n");
	printf("_________________________________________________________________\n\n");
	int n;
	int b[20]={0},m[20]={0},M[20]={0},ni[20]={0};
	scanf("%d",&n);
	getchar(); 
	int i;
	//为数组b【】和m【】赋值 
	for(i=1;i<=n;++i)
	{
		scanf("%d",&b[i]);
		getchar(); 
	}
	for(i=1;i<=n;++i)
	{
		scanf("%d",&m[i]);
		getchar(); 
	}
	//打印同余式组 
	printf("\n求解的同余式组为:"); //
	for(i=1;i<=n;++i)//
	{//
		printf("\n\tx ≡ %5d (mod %5d)",b[i],m[i]);//
	}//
	//计算mm 
    printf("\n\n  1、计算mm\n\t mm=1") ; //
	 int mm = 1;
	 for(i=1;i<=n;++i)
	{
		mm = mm*m[i];
		printf("*%d",m[i]); //
	}
	//计算M[i] 
	printf("\n\n  2、计算M[i]:") ; //
	for(i=1;i<=n;++i)
	{
		M[i] = mm/m[i];
		printf("\n\t M[%d] = mm/m[%d] = %5d / %5d = %5d",i,i,mm,m[i],M[i]); //
	}
	//求逆 
	printf("\n\n  3、求M[i]模m[i]的逆元: 即求解ni[i]*M[i] ≡ 1 (mod = m[i])中的ni[i]") ; //
	for(i=1;i<=n;++i)
	{
		ni[i] = NI(M[i],m[i]) ;
		printf("\n\t ni[%d]:   %5d %5d≡ 1(mod %5d) ",i,ni[i],M[i],m[i]) ;//
	}
	//求解X
	printf("\n\n  4、求X = (Σni[i]*M[i]*b[i])(mod mm) , 1<= i <=n") ; // 
	int X = 0;
	printf("\n\t X = 0");//
	for(i=1;i<=n;++i)
	{
		X = X + ni[i]*M[i]*b[i] ;
		printf("+%d*%d*%d",ni[i],M[i],b[i]);//
	}
	X = X%mm; 
	printf(" (mod %d)",mm);//
	//输出结果
	printf("\n\n因此,最后的结果为:");
	printf("\n\t--------   x ≡ %d (mod %d)  ---------\n\n",X,mm);
	 return 0;
}


int NI(int a,int m)
{
	int s[100]={0};
    int t[100]={0};
    int q[100]={0};
    int r[100]={0};
    s[0] = 1 ; s[1] = 0 ;
	t[0] = 0 ; t[1] = 1 ;
	r[0] = a ; r[1] = m ;
	q[1] = r[0] / r[1] ;
	r[2] = r[0] % r[1] ;
    r[3] = r[1] % r[2];
    int j=2;
    while(1)
    {
    	q[j]   = r[j-1] / r[j];
    	r[j+1] = r[j-1] - q[j]*r[j];
    	s[j]   = s[j-2] -  q[j-1]*s[j-1] ;
    	t[j]   = t[j-2] -  q[j-1]*t[j-1] ;
		if(r[j+1]==0) break; 
        j++;
	}
	if(s[j]<0) return (m+s[j]); 
	return s[j];	
 } 
 

运行
在这里插入图片描述

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用C语言实现中国剩余定理的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 求出a和b的最大公约数 int gcd(int a, int b) { if (b == 0) { return a; } return gcd(b, a % b); } // 求出a和b的最小公倍数 int lcm(int a, int b) { return a * b / gcd(a, b); } // 扩展欧几里得算法 // 求出a和b的最大公约数gcd以及满足ax+by=gcd的整数解x、y void extgcd(int a, int b, int *gcd, int *x, int *y) { if (b == 0) { *gcd = a; *x = 1; *y = 0; return; } extgcd(b, a % b, gcd, y, x); *y -= *x * (a / b); } // 使用中国剩余定理求解 // m和r分别为同余方程组的模数和余数 // count为方程的个数 // 返回值为满足条件的最小解 int CRT(int *m, int *r, int count) { int M = 1; for (int i = 0; i < count; i++) { M = lcm(M, m[i]); // 求出模数的最小公倍数 } int x = 0; for (int i = 0; i < count; i++) { int Mi = M / m[i]; int gcd, y, z; extgcd(Mi, m[i], &gcd, &y, &z); // 求解Mi和m[i]的最大公约数和对应的x、y x = (x + Mi * y * r[i]) % M; // 对应的解为x ≡ ∑(Mi * r[i] * y) (mod M) } return x; } int main() { int m[] = {3, 5, 7}; // 模数 int r[] = {2, 3, 2}; // 余数 int count = 3; // 方程个数 int x = CRT(m, r, count); // 求出最小解 printf("x = %d\n", x); return 0; } ``` 在这个例子中,我们使用了扩展欧几里得算法和最小公倍数来实现求解最小解的操作。同时,我们也可以根据需要修改模数和余数的个数以及对应的值来实现不同的计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值