问题:模线性同余方程组: x = a1 ( mod n1 ) x = a2 ( mod n2 ) .... x = ak ( mod nk )给定 A ( a1, a2 , ... , ak ) , N ( n1, n2, ..., nk ) 求 X 。通常分为两种 一, ( Ni, Nj ) 之间两两互质 二, ( Ni, Nj ) 之间不都互质一 ( Ni, Nj ) 之间两两互质 定理( 见算法导论 P874 ): 如果 n1, n2 , ... , nk 两两互质, n = n1*n2*..*nk ,则对任意整数 a1,a2,a3..,ak , 方程组 x = ai ( mod ni ) 关于未知量 x 对 模n 有唯一解从输入 ( a1, a2, ... , ak ) 计算出 a : 定义 定义 可以得到:代码模板 a = a[i] ( mod n[i] ) ( i = 0. 1. 2. .. k ) { n[i] 之间两两互质 }View Code
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 1010;
LL a[N], n[N], nn, k;
LL Exgcd( LL a, LL b, LL &x, LL &y )
{
if( b == 0 ){ x = 1; y = 0; return a; }
LL r = Exgcd( b, a%b, x, y );
LL t = x;
x = y; y = t - a/b*y;
return r;
}
LL mul( LL a, LL b )
{
LL res = 0;
while( b )
{
if( b&1 ) if( (res+=a) >= nn ) res -= nn;
a <<= 1; if( a >= nn ) a -= nn;
b >>= 1;
}
return res;
}
LL inverse( LL A, LL B )
{//求逆元
LL x, y;
Exgcd( A, B, x, y );
return (x%B+B)%B;
}
LL China(){
scanf("%lld", &k); // k个 模同余等式
for(int i = 0; i < k; i++)
scanf("%lld", &a[i] );
for(int i = 0; i < k; i++)
scanf("%lld", &n[i] );
nn = 1;
for(int i = 0; i < k; i++)
nn *= n[i];
LL A = 0;
for(int i = 0; i < k; i++)
{
// ci = mi * (mi^-1 mod ni )
// ai * ci
LL m = nn/n[i], m1 = inverse( m, n[i] );
LL c = m*m1;
A = ( A + mul( a[i], c ) ) % nn;
}
return A;
}
int main()
{
printf("%lld
",China() );
return 0;
}二( Ni, Nj ) 之间不都互质 x = ai ( mod mi ) 1 <= i <= k 先考虑k==2的情况: x = a1 ( mod m1 ) x = a2 ( mod m2 ) 方程组有解的充分必要条件是: d | (a1-a2) ,其中 d = (m1,m2)证明如下: 必要性: 设 x 是上面同余方程组的解,从而存在整数q1,q2使得x=a1+m1*q1,x=a2+m2*q2,消去x即得a1-a2 = m2q2-m1q1。由于d= GCD(m1,m2),故d | (a1-a2)。 充分性: 若d=GCD(m1,m2) | (a1-a2)成立,则方程m1*x + m2*y = a1-a2有解。 设解为x0,y0。那么m2*y0 = a1-a2 ( mod m1 ) 记x1 = a2+m2*y0,可以知道 x1=a2 ( mod m2 ),且x1 = a2+m2*y0 = a2 + ( a1-a2) = a1 ( mod m1 ) 所以 x1 = a2 ( mod m2 ) = a1 ( mod m1 ) 所以 x = x1 ( mod GCD[m1,m2] ) 另外,若x1与x2都是上面同余方程组的解,则 x1 = x2 ( mod m1 ), x1 = x2 ( mod m2 ), 由同余的性质得 x1 = x2 ( mod [m1,m2] ),即对于模[m1,m2],同余方程组的解释唯一的。 证毕。C++代码模板:
#include
typedef long long LL;
LL ExGcd( LL a, LL b, LL &x, LL &y )
{
if( b == 0 ) { x=1;y=0; return a; }
LL r = ExGcd( b, a%b, x, y );
LL t = x; x = y; y = t - a/b*y;
return r;
}
LL Modline( LL r[], LL a[], int n )
{
// X = r[i] ( mod a[i] )
LL rr = r[0], aa = a[0];
for(int i = 1; i < n; i++ )
{
// aa*x + a[i]*y = ( r[i] - rr );
LL C = r[i] - rr, x, y;
LL d = ExGcd( aa, a[i], x, y );
if( (C%d) != 0 ) return -1;
LL Mod = a[i]/d;
x = ( ( x*(C/d)% Mod ) + Mod ) % Mod;
rr = rr + aa*x; // 余数累加
aa = aa*a[i]/d; // n = n1*n2*...*nk
}
return rr;
}
// test
int main()
{
int n;
LL r[10], a[10];
while( scanf("%d", &n) != EOF)
{
for(int i = 0; i < n; i++)
scanf("%lld", &r[i] );
for(int i = 0; i < n; i++)
scanf("%lld", &a[i] );
printf("%lld
", Modline( r, a, n ) );
}
return 0;
}转至http://www.cnblogs.com/yefeng1627/archive/2012/12/31/2841058.html