Question 256. Luogu P1495 Chinese Remainder Theorem - [Template] Chinese Remainder Theorem (CRT)/Cao Chong Pig Raising


Question 256. Luogu P1495 Chinese Remainder Theorem - [Template] Chinese Remainder Theorem (CRT)/Cao Chong Pig Raising


1. About the Chinese Remainder Theorem CRT

1 Overview

It is used to solve the system of univariate linear congruence equations (b1, b2, ..., bk are relatively prime in pairs) of the following form: In
insert image description here
layman's terms, it is possible to find a number x, and the remainder of the number to bi is equal to ai, and i ranges from 1 to k.

2. Algorithm steps

Let the divisor be ai and the remainder be bi, i∈[0,N) and i∈Z. The required number is res
① Find the product n of all divisors ai
② Find the multiple m of all divisors except ai, m=n/ai
③ Use the extended Euclidean algorithm or Fermat's little theorem to get the inverse of m mm
④ Multiply m by mm by the remainder bi, and add the result to res. If the total result seems to be very large, perform the modulo operation according to the modulo formula
⑤i++, go back to ②, and end the operation when i=N

Second, the topic

insert image description here

3. Problem solving

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn=1e5+1;

ll a[maxn],b[maxn];

ll ex_gcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得算法
{
    
    
    if(b==0)
    {
    
    
        x=1;
        y=0;
        return a;
    }
    ll ans=ex_gcd(b,a%b,x,y);
    ll tmp=x;
    x=y;
    y=tmp-a/b*y;
    return ans;
}

ll CRT(ll a[],ll b[],int N)
{
    
    
    ll n=1;
    for(int i=0;i<N;i++)//得到所有除数的乘积
    {
    
    
        n*=a[i];
    }
    ll res=0;
    for(int i=0;i<N;i++)
    {
    
    
        ll m=n/a[i];//得到a[i]以外所有的除数的倍数m
        ll mm,y;
        //利用扩欧求m的逆元mm
        ex_gcd(m,a[i],mm,y);
        mm=(mm%a[i]+a[i])%a[i];//最小正整数x为(x%b/gcd(a,b)+b/gcd(a,b))%b/gcd(a,b)
        res=(res%n+m*mm*b[i]%n)%n;//线性同余方程组的唯一解res为(m*mm*余数)求和
    }
    return res;
}

int main()
{
    
    
    int N;
    cin>>N;
    for(int i=0;i<N;i++)
    {
    
    
        cin>>a[i]>>b[i];
    }
    ll res=CRT(a,b,N);
    cout<<res;
}

For a detailed explanation of CRT, please see this article by Niuren and oi-wiki


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324346175&siteId=291194637