0
点赞
收藏
分享

微信扫一扫

中国剩余定理

i奇异 2022-05-02 阅读 77
算法c++

中国剩余定理

概念

定理介绍和证明

例题

求解模线性方程组,形如:
a ≡ B[1](mod W[1])
a ≡ B[2](mod W[2])


a ≡ B[n](mod W[n])
W,B已知,W[i]>0 且所有W互质,求a (最小正整数解)。

代码实现
#include <iostream>
using namespace std;
//中国剩余定理
//所有模数互质 
typedef long long ll;

int W[51],B[51];

ll exgcd(ll a, ll b, ll &x, ll &y)//扩欧算法 
{
	if (!b)
    {
        x = 1,y = 0;
        return a;
    }
    ll gcd = exgcd(b, a % b, x, y);
    
	ll tmp = x;
	x = y;
	y = tmp - a / b * y; 
    return gcd;
}
int China(int * w, int * b, int k)
{
	ll x, y , a = 0;
	int m;
	ll N = 1;
	for(int i = 1; i < k + 1; i ++) N *= w[i];
	
	for(int i = 1; i < k + 1; i ++)
	{
		m = N / w[i];
		exgcd(w[i],m,x,y);
		a = (a + y *m * b[i]) % N;
	}
	return (a + N) % N;
}
int main()
{
  int n;
  cin >> n;//方程数

  for(int i = 1; i <= n; i ++)
  	cin >> W[i] >> B[i];
  
  int res = China(W,B,n); 
  cout << res <<endl;
  
  return 0;
}

解一般意义同余方程通用方案(模数不一定两两互素)

求解方案论述
例题
代码实现
#include <iostream>
using namespace std;

typedef long long ll;

ll exgcd(ll a, ll b, ll &x, ll &y)
{
	 if (!b)
    {
        x = 1; y = 0;
        return a;
    }
    ll d = exgcd(b, a % b, y, x);
    y -= (a/b) * x;
    return d;
}
int main()
{
  int n;
  cin >> n;
  
  bool flag = true;
  ll a1, m1; 
  cin >> a1 >> m1;
  
  for(int i = 0; i < n - 1; i ++)
  {
  	ll a2, m2;
  	cin >> a2 >> m2;
  	
  	ll k1, k2;
  	ll d = exgcd(a1,a2,k1,k2);
  	if((m2 - m1) % d)
  	{
  		flag = false;
  		break;
	}
	  k1 *= (m2 - m1) / d;
	  k1 = (k1 % a2 +a2) % a2;//adjust to minimal
	  
	  m1 = a1 * k1 + m1;//特解 
	  a1 = a1 / d * a2;// X = A1 K + M1 
	  
  }
  if(flag)
  {
  	cout << (m1 % a1 + a1) % a1 <<endl;
  }
  else puts("-1");
  return 0;
}

举报

相关推荐

0 条评论