问题:今有物不知其数,三三数之有二,五五数之有三,七七数之有二,问物有多少?
数学表达式如下,求x。
x mod 3=2
x mod 5=3
x mod 7=2
定理1:
设m1,m2,…mk是两两互素的正整数,则对任意b1,b2,…,bk,同余方程组x mod m1 = b1 mod m1,
x mod m2 = b2 mod m2,
…
x mod mk=bkmod mk,
其解为: x=(M1’M1b1+M2’M2b2+…+M’kMkbk )mod m
其中:m=m1m2…mk, Mi=m/mi, MiMi’ mod mi=1 显然(Mi,mi)=1即Mi’是Mi的逆元
上面的例子解如下:
m1=3 m2=5 m3=7 b1=2 b2=3 b3=2
m=m1*m2*m3=3*5*7=105
M1=m/m1=5*7=35 M1’=2
M2=21, M2'=1
M3=15, M3'=1
则解X为
X=(M1’*M1*b1+M2’*M2*b2+M3’*M3*b3)%m= (140+63+30)%105 = 23
逆元的求法(C#代码,必须保证num和modeNum互质才有解):
publicstaticintGetOpposite(intnum,intmodeNum)
{
intopposite =0;
intremainder =0;
inttemp1 =0;
inttemp2 =1;
//将较小的数作为 modeNum
if(modeNum > num)
{
num = num + modeNum;
modeNum = num - modeNum;
num = num - modeNum;
}
//将num 保存起来,如果最终的余数小于零,将其转换成大于零的数
inttempNum = num;
do
{
remainder = num % modeNum;
if(remainder!=0)
{
opposite = -1* num / modeNum * temp2 + temp1;
}
temp1 = temp2;
temp2 = opposite;
num = modeNum;
modeNum = remainder;
}
while(remainder!=0);
returnopposite>0?opposite:opposite+tempNum;
}
代码二,求逆元:
//扩展欧几里得
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if(a==0){
x=0;
y=1;
return b;
}
long long g=exgcd(b%a,a,x,y);
long long tem=y;
y=x;
x=tem-(b/a)*y;
return g;
}
long long inv(long long a,long long n)//求逆元
{
long long x,y;
exgcd(a,n,x,y);
return (x%n+n)%n;
}
long long apmodm(long long a,long long b,long long m){//a^p mod m
if(b==0)return 1%m;
if(b==1)return a%m;
long long tem= apmodm(a,b>>1,m);
if(!(b&1))return tem*tem%m;
else return(((tem*tem)%m)*(a%m))%m;
}
//一个公式:求 p^0+p^1+p^2....p^n mod m 的余数
long long solve(long long p,long long n,long long m)
{
if((p-1)%m==0) return (apmodm(p,n+1,m*(p-1))-1)/(p-1);//公式 a/b mod m==a mod(m*b)/b 当 b|a的时候
return ((apmodm(p,n+1,m)-1)*inv(p-1,m))%m;
}
//分治的方法
long long solve(long long p,long long n,long long m)
{
if(n==0)return 1%m;
long long tem=solve(p,n>>1,m);
if(n&1)return tem*(apmodm(p,(n>>1)+1,m)+1)%m;
return (solve(p,n-1,m)+apmodm(p,n,m))%m;
}