中国剩余定理,扩展中国剩余定模板。

我们两清 提交于 2019-11-27 21:53:09

解决的问题:求一个最小正整数x。x满足条件 x % m[ ] = a[ ];

1 中国剩余定理只能解决m互质时;

2 扩展中国剩余定理可以解决的m不互质,但是可以m互质时用扩展中国剩余定理会慢。

中国剩余定理的证明我说一下把,扩展的不熟练怕误人子弟。

 

首先说一下值的意思。

lcm = m1*m2*m3.....     Mi = lcm/mi

证明: ①mi和其他数是互质的和其他值的乘积同样互质  gcd(Mi, mi) == 1

    ②由扩展欧几里得性质(ax+by=c 当且仅当c%gcd(x,y) = 0) Mi*x + mi*y = 1

    ③两边模mi,-> Mi*x % mi = 1, 令ei = Mi*x

                                                         即ei ≡ 0(mod mj), j != i 

                                                                  ei ≡ 1(mod mj), j = i

    ④故一个解是e1*a1 + e2*a2 + ....... + en*an

 

中国剩余定理模板  洛谷模板题https://www.luogu.org/problem/P3868

求x:x % m[] = a[]; 并且m数组是互质的。①适用于a,m为非负整数,如果又a有负数,先转化成正,下边有写。②乘时可能爆ll,有时需要快速乘。
ll a[100], m[100];
ll exgcd(ll a, ll b, ll &x, ll &y){ //扩展欧几里得
  if(!b){
    x = 1; y = 0;
    return a;
  }
  ll gcd = exgcd(b, a%b, y, x);
  y -= a/b * x;
  return gcd;
}
ll chinese_lest(int n){
  ll lcm = 1, ans = 0, x, y;
  for(int i = 1; i <= n; i++) lcm*=m[i];
  for(int i = 1; i <= n; i++){
ll mi = lcm/m[i];
ll gcd = exgcd(m[i], mi, x, y);
    ans = (ans + y*mi*a[i])%lcm;
  }
  return (lcm + ans)%lcm;
}
int main(){
    int n; cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) cin >> m[i];
//for(int i = 1; i <= n; i++) a[i] = (a[i]+m[i])%m[i]; //有负数的情况
cout << chinese_lest(n) << endl;
}

 

扩展中国剩余定理模板 洛谷模板题https://www.luogu.org/problem/P4777

#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;

//求x:x % m[] = a[]; m数组不互质,无解输出-1.
ll a[100005], m[100005];
ll exgcd(ll a, ll b, ll &x, ll &y){
    if(!b){
    x = 1; y = 0;
    return a;
    }
    ll gcd = exgcd(b, a%b, y, x);
    y -= a/b * x;
    return gcd;
}
ll qmul(ll a, ll b, ll mod){
    ll tot = 0;
    while(b){
        if(b&1) tot = (tot+a)%mod;
        a = (a+a)%mod;
        b>>=1;
    }
    return tot;
}
ll exchinese_lest(int n){
    ll x, y;
    ll M = m[1], ans = a[1];
    for(int i = 2; i <= n; i++){
        ll A = M, b = m[i], c = (a[i] - ans % b + b) % b;
        ll gcd = exgcd(A, b, x, y), bg = b / gcd;
        if(c % gcd != 0) return -1;
        x = qmul(x, c / gcd, bg);
        ans += x * M;
        M *= bg;
        ans = (ans % M + M) % M;
    }
    return (ans % M + M) % M;
}
int main(){
    int n; cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) cin >> m[i];
    cout << exchinese_lest(n) << endl;
    return 0;
}

 

 

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!