模板题 链接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;
}