中国剩余定理----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;
}

猜你喜欢

转载自blog.csdn.net/holly_Z_P_F/article/details/83301553