Chinese Remainder Theorem (CRT) and expand (ExCRT)

Chinese Remainder Theorem CRT

Derivation

Given \ (n-\) th congruence equation
\ [\ left \ {\ begin {aligned} x & \ equiv a_1 \ pmod {m_1} \\ x & \ equiv a_2 \ pmod {m_2} \\ & ... X & \\ \ equiv A_N \ M_n PMOD {} \ the aligned End {} \ right. \]
\ (m_1, M_2, ..., M_n \) pairwise mass

\(M = \prod_{i=1}^{n} m_i\),求\(x \mod M\)

The solution to this problem is to construct.

We assume that the final answer in the form of a \ (n \) and type a term, the structure of each congruence equation of reaction coefficient in the corresponding term.

To configured separately for each item, for each item requires multiplied by a suitable number, such that each coefficient has no effect on the configuration of the results of the other equations.

Readily occur configured
\ [M_i = \ frac {M } {m_i} \]

Obviously this number only in analog \ (m_i \) is not equal to \ (0 \) , then the coefficient of change will not affect other equations.

Now we hope that mold \ (m_i \) in the sense that \ (a_i \) , but the last remaining structure under a \ (M_i \) . Simple and crude multiplied by \ (M_i \) in the mold \ (m_i \) reverse the sense of yuan \ (inv_ m_i {} (M_i) \) , so that the mold \ (m_i \) becomes the sense of \ ( 1 \) , and then multiplied by \ (a_i \) to construct out.

In summary, the answer is
\ [\ sum_ {i = 1 } ^ {n} M_i inv_ {m_i} (M_i) a_i \ mod {M} \]

Modulo prime condition ensures that the \ (M_i \) non \ (0 \) , to ensure that the \ (inv_ {m_i} (M_i ) \) exists.

achieve

Most of all questions \ (m_i \) is a prime number, find the inverse \ (QPow \) can be.

For the general case, the exgcd on the line.

Board questions: Luo Gu Cao Chong pig P1495

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
typedef long long ll;

namespace ExGcd{
    ll x,y;
    ll ExGcd(ll a,ll b){
        ll ans;
        if(a%b==0){
            x=0;y=1;ans=b;
        }else{
            ans=ExGcd(b,a%b);
            ll x1=x,y1=y;
            x=y1;y=x1-a/b*y1;
        }
        return ans;
    }
    bool SolveEqu(ll a,ll b,ll c){
        ll d=ExGcd(a,b);
        if(c%d!=0) return 0;
        x*=c/d;y*=c/d;
        x=(x%b+b)%b;
        y=(c-a*x)/b;
        return 1;
    }
}
ll Inv(ll a,ll m){
    ExGcd::SolveEqu(a,m,1);
    return ExGcd::x;
}

const ll CRTN=20;
namespace CRT{
    ll N;
    ll m[CRTN],a[CRTN];
    ll Sol(){
        ll ans=0,M=1;
        for(ll i=1;i<=N;i++) M*=m[i];
        for(ll i=1;i<=N;i++){
            ll Mi=M/m[i];
            ans=(ans+Mi*Inv(Mi,m[i])*a[i])%M;
        }
        return ans;
    }
}
int main(){
    using namespace CRT;
    scanf("%lld",&N);
    for(ll i=1;i<=N;i++)
        scanf("%lld%lld",&m[i],&a[i]);
    printf("%lld",Sol());
    return 0;
}

Expanding Chinese remainder theorem ExCRT

ExCRT and CRT does not matter, as ExLucas and nothing to do with Lucas as (

In fact, from the point of view of pure reasoning, ExCRT may have to miss a little (

Derivation

Problems with the CRT, but the modulus is arbitrary and does not require coprime.

At this time, we can not guarantee the existence of the inverse element. So how to solve this problem?

Consider how to merge the two equations. If we find a way to merge, we will be able to do the same \ (n \) equations in turn merged, get an answer.
\ [\ Left \ {\ begin
{aligned} x & \ equiv a_1 \ pmod {m_1} \\ x & \ equiv a_2 \ pmod {m_2} \ end {aligned} \ right. \] Removed congruences into uncertain equation
\ [\ left \ {\ begin {aligned} x & = m_1 y_1 + a_1 \\ x & = m_2 y_2 + a_2 \ end {aligned} \ right. \]

Thereby obtaining
\ [m_1 y_1 + a_1 = m_2 y_2 + a_2 \]

Just find a group to meet the style \ (y_1 \) and \ (y_2 \) , can be calculated backward \ (the X-\) , to achieve the merger.

And we get is one of a binary equation, you can use exgcd solved.

Into the standard type
\ [m_1 y_1 - m_2 y_2 = a_2 - a_1 \]

Solution it wants. If there is no solution, indicating congruent equation has no solution.

Then finally obtained combined of formula
\ [x \ equiv m_1 y_1 + a_1 \ pmod {lcm (m_1, m_2)} \]

achieve

The only caveat is that the solution should have been solving equations \ ((m_1, -m_2, A_2-A_1) \) , but ExGCD hard to deal with negative numbers, so the \ (m_2 \) into a \ (m_1 \) . Because we do not need to use \ (y_2 \) , there apparently is not affected.

Board questions: poj2891 Strange Way to Express Integers or Luo Gu P4777 expand Chinese remainder theorem (EXCRT)

Get caught multiplication burst ll,Too lazy to change

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
typedef long long ll;

namespace ExGcd{
    ll x,y;
    ll ExGcd(ll a,ll b){
        ll ans;
        if(a%b==0){
            x=0;y=1;ans=b;
        }else{
            ans=ExGcd(b,a%b);
            ll x1=x,y1=y;
            x=y1;y=x1-a/b*y1;
        }
        return ans;
    }
    bool SolveEqu(ll a,ll b,ll c){
        ll d=ExGcd(a,b);
        if(c%d!=0) return 0;
        x*=c/d;y*=c/d;
        x=(x%b+b)%b;
        y=(c-a*x)/b;
        return 1;
    }
}
ll Gcd(ll a,ll b){
    if(a%b==0) return b;
    return Gcd(b,a%b);
}
namespace ExCRT{
    ll a1,m1;
    void Init(){
        a1=0;m1=1;
    }
    void Expand(ll a2,ll m2){
        ExGcd::SolveEqu(m1,m2,a2-a1);
        ll y1=ExGcd::x;
        ll mn=m1*m2/Gcd(m1,m2);
        a1=(m1*y1+a1)%mn;
        m1=mn;
    }
}
int main(){
    ll N;scanf("%lld",&N);
    ExCRT::Init();
    for(ll i=1;i<=N;i++){
        ll a,m;scanf("%lld%lld",&m,&a);
        ExCRT::Expand(a,m);
    }
    printf("%lld",ExCRT::a1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/sun123zxy/p/crt.html