中國剩餘定理詳解

對於一個數x,知道:ios

x%m1=a1,x%m2=a2,x%m3=a3.(m1,m2,m3)互質。git

求x。spa

咱們來形象化一下:code

一個數,%3=1,%5=1,%7=2,這個數是什麼?blog

稍微試一試發現是16,那麼怎麼正常地算出來呢?get

咱們首先要弄明白一件事:string

若是a%b==c,那麼a加上一個b的倍數,%b仍是餘c。這個仍是很顯而易見的吧。it

那我咱們想要求出的x,能夠分爲三個數相加io

x=A1+A2+A3.其中A1%3=1,A2%5=1,A3%7=2.A二、3是3的倍數,A一、3是5的倍數,A一、2是7的倍數。class

咱們先求A3,A3要知足是五、3的倍數,也要知足%7=2,。

首先,咱們知道它必定是15的倍數,那麼咱們要知道怎樣才能知足%7=2

若是要求%7=2,只用求出來%7=1,而後再乘2就能夠了。

因而獲得了以下方程

15*t≡1(mod 7)

似曾相識,這個方程至關於15*t+7*y=1能夠用拓展歐幾里得求解。

而後,咱們知道t=1,也就是15*1%7=1,因此15*1*2%7就等於2.

因而A3就等於15*1*2=30,

以此類推,求出來A一、A2,最後加起來就是答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#define REP(i,k,n)  for(LL i=k;i<=n;i++)
#define in(a) a=read()
using namespace std;
typedef long long LL;
inline LL read(){
    LL x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            f=-1;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return x*f;
}
LL T;
inline void exgcd(LL A,LL B,LL &x,LL &y){
    if(B==0)  x=1,y=0;
    else  exgcd(B,A%B,x,y),T=x,x=y,y=T-A/B*y;
}
LL n,a[50],b[50],m[50],t[50];
LL M=1,ans;
int main(){
    in(n);
    REP(i,1,n)  in(a[i]),in(b[i]),M=M*a[i];
    REP(i,1,n){
        m[i]=M/a[i];
        LL x,y;
        exgcd(m[i],a[i],x,y);
        t[i]=x;
        ans=((ans+(b[i]*t[i]*m[i])%M+M)%M)%M;
    }
    cout<<ans;
    return 0;
}
/*3
3 1
5 1
7 2*/
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息