推论1:方程ax=b(mod n)对于未知量x有解,当且仅当gcd(a,n) | b。
推论2:方程ax=b(mod n)或者对模n有d个不同的解,其中d=gcd(a,n),或者无解。
定理1:设d=gcd(a,n),假定对整数x和y满足d=ax+by(比如用扩展Euclid算法求出的一组解)。如果d | b,则方程ax=b(mod n)有一个解x0满足x0=x*(b/d) mod n 。特别的设e=x0+n,方程ax=b(mod n)的最小整数解x1=e mod (n/d),最大整数解x2=x1+(d-1)*(n/d)。
定理2:假设方程ax=b(mod n)有解,且x0是方程的任意一个解,则该方程对模n恰有d个不同的解(d=gcd(a,n)),分别为:xi=x0+i*(n/d) mod n 。
证明过程请详见 《算法导论》
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
int EXTENDED_EUCLID(int a,int b,int &x,int &y)//扩展欧几里德算法
{
if(b==0)
{
x=1;
y=0;
return a;
}
int r=EXTENDED_EUCLID(b,a%b,x,y);
int temp=x;
x=y;
y=temp-a/b*y;
return r;
}
int MODULAR_LINEAR(int a,int b,int n)//求解模线性方程
{
int d,x,y;
int x0;
d=EXTENDED_EUCLID(a,n,x,y);
x0=(x*(b/d)+n)%n;
return x0;
}
//当时鱼头让我们研究的时候,没有考虑得太仔细,上面的方程只能求出一个可行解
//而下面的函数能够求出最小的整数解,甚至在模n内任意的解
long long MODULAR_LINEAR(long long a,long long b,long long n)//求解模线性方程
{
long long d,x,y;
long long x0;
d=EXTENDED_EUCLID(a,n,x,y);
if(b%d)
return -1;
x0=(x*(b/d))%n+n;//确保是正数
x0%=(n/d);//x0是第一个大于0的整数解
return x0;
}
int CHINESE_RESIDUE_THEOREM(int n[],int b[],int k)//求解模线性方程组,所有数据从1号下标开始存储
{
int result=0;
int i;
int N=1;
int *m=new int [k+1];
int *reversem=new int [k+1];
int sum=0;
for(i=1;i<=k;i++)
{
N*=n[i];
}
for(i=1;i<=k;i++)
{
m[i]=N/n[i];
reversem[i]=MODULAR_LINEAR(m[i],1,n[i]);
sum+=m[i]*reversem[i]*b[i];
}
result=sum%N;
return result;
}
int main ()
{
int num;
int i;
printf("参考格式:X mod n[i] = b[i]\n");
cout<<"请输入方程的个数:";
cin>>num;
int *n=new int [num+1];
int *b=new int [num+1];
for(i=1;i<=num;i++)
{
cout<<"请输入第"<<i<<"个方程的n和b:";
cin>>n[i]>>b[i];
}
int result=CHINESE_RESIDUE_THEOREM(n,b,num);
cout<<"解为:";
cout<<result<<endl;
cout<<"谢谢你的使用"<<endl;
system("pause");
return 0;
}