中国剩余定理模板

以一个经典例子配合代码来理解:

x%3=2;  x%5=3;  x%7=2;

1.求最小公倍数:M=3*5*7=105。

2.依照余数求各个数的基础数:

105/3=35,35%3=2;

105/5=21,21%5=1,即63%5=3;

105/7=15,15%7=1,即30%7=2。

3.求和sum=35+63+30=128;

4.求最小满足条件的x=(M+sum%M)%M。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;

//扩展欧几里得,ax+by=gcd(a,b) 
ll e_gcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	ll res=e_gcd(b,a%b,y,x);
	y-=(a/b)*x;
	return res;
}

//中国剩余定理,pri[]存放互质的数,r[]存放余数,n为个数 
ll china(ll pri[],ll r[],ll n){
	ll M=1,m,d,res=0;
	for(int i=0;i<n;i++) 
		M*=pri[i]; //最小公倍数
	for(int i=0;i<n;i++){
		m=M/pri[i]; //m为除当前这个数不能整除以外都能够被其他数整除,就是其他数的最小公倍数
		ll x,y;
		d=e_gcd(pri[i],m,x,y); // pri[i]*x+m*y=gcd(pri[i],m]
		res=(res+y*m*r[i])%M; 
	} 
	return (res%M+M)%M;  //满足的最小解 
}

ll pri[20],r[20];
int main(){
	int n;
	while(~scanf("%d",&n)){
		for(int i=0;i<n;i++)
			scanf("%lld %lld",&pri[i],&r[i]);
		ll ans=china(pri,r,n);
		printf("%lld\n",ans);
	}
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值