1. 程式人生 > >中國剩餘定理----51nod1079

中國剩餘定理----51nod1079

模板題  連結51nod1079

這道題是中國剩餘定理的模板題,但是這道題範圍不大,還可以暴力求解,只是複雜度高些。

下面說下孫子定理(中國剩餘定理)

定理詳述參見百度百科

求法

要求出的是----x     m陣列中 存的是x與其取餘的數    p陣列中存的是x於m[i]取餘得到的餘數

我們先求出 M------就是m陣列種連續乘起來

再求出 f 陣列------就是M / m[ i ]    (f [ i ] 也就是除了m[ i ]以外的m陣列乘起來)

再求出 t 陣列------t [ i ] 是 f [ i ]在模m[ i ]意義下的逆元(

乘法逆元的求法

再將t[ i ] * p[ i ] * f[ i ]  從1-n累加起來(在模M的情況下

參見程式碼和註釋

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=1e4+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
ll p[maxn],m[maxn],f[maxn],t[maxn];
ll n,k,M;
ll pow_mod(ll x,ll n,ll mod){
    ll res=1;
    while(n){
        if(n&1)res=(x*res)%mod;
        x=(x*x)%mod;
        n>>=1;
    }
    return (res+mod)%mod;
}
int main(){
    scanf("%lld",&n);
    M=1;
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&m[i],&p[i]);
        M*=m[i];//連乘求出M
    }
    for(int i=1;i<=n;i++){
        f[i]=M/m[i];//求出f陣列
        t[i]=pow_mod(f[i],m[i]-2,m[i]);//費馬小定理求乘法逆元
    }

    for(int i=1;i<=n;i++){
        k=(k+p[i]*t[i]*f[i])%M;//注意 累加是在模M的情況下累加
    }
    printf("%lld\n",k);

    return 0;
}