Problem 1402 猪的安家(中国余数定理)

Problem Description

Andy和Mary养了很多猪。他们想要给猪安家。但是Andy没有足够的猪圈,很多猪只能够在一个猪圈安家。举个例子,假如有16头猪,Andy建了3个猪圈,为了保证公平,剩下1头猪就没有地方安家了。Mary生气了,骂Andy没有脑子,并让他重新建立猪圈。这回Andy建造了5个猪圈,但是仍然有1头猪没有地方去,然后Andy又建造了7个猪圈,但是还有2头没有地方去。Andy都快疯了。你对这个事情感兴趣起来,你想通过Andy建造猪圈的过程,知道Andy家至少养了多少头猪。

Input

输入包含多组测试数据。每组数据第一行包含一个整数n (n <= 10) – Andy建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示Andy建立了ai个猪圈,有bi头猪没有去处。你可以假定(ai, aj) = 1.

Output

输出包含一个正整数,即为Andy家至少养猪的数目。

Sample Input

3
3 1
5 1
7 2

Sample Output

16
点击打开链接

很裸的中国余数定理的应用:
设m1,m2,…mk是两两互素的正数,则对任意的整数b1,b2,…bk,同余方程组
X ≡ b1 (mod m1)  意思是X和b1对m1取余的结果相同
X ≡ b2 (mod m2)
X ≡ bk (mod mk)
n其解为
nX = ((y1*M1*b1)+(y2*M2*b2)+…+(yk*Mk*bk)  )mod m;
n其中
m = m1*m2*…*mk;
Mi = m / mi;
(yi *Mi) mod mi = 1
n如何求yi
因为 Mi 和mi 互质,gcd(Mi, mi)=1
必然存在 yi*Mi + xi*mi = 1(扩展Euclid)


#include <cstdio>
#include <set>
#include <string>
#include <iostream>
#include <cstring>
#include <algorithm>
#define LL __int64
using namespace std;
LL y[20],mi[20],b[20],m,M[20],n;
LL ex_eulicd(LL aa,LL bb,LL &x,LL &y)
{
	LL temp,d;
	if(bb==0)
	{
		x=1;
		y=0;
		return aa;
	}
	d=ex_eulicd(bb,aa%bb,x,y);
	temp=x;
	x=y;
	y=temp-aa/bb*y;
	return d;
}
int main()
{
	LL i,res;
    ///freopen("D://p.txt","r",stdin);
	//freopen("D:\\oo.txt","w",stdout);
	while(scanf("%I64d",&n)!=EOF)
	{
		res=0;
		m=1;
		for(i=0;i<n;i++)
		{
			scanf("%I64d%I64d",&mi[i],&b[i]);
			m*=mi[i];
		}
		for(i=0;i<n;i++)
			M[i]=m/mi[i];
		for(i=0;i<n;i++)
		{
			LL xx,yy;
			LL d=ex_eulicd(M[i],mi[i],xx,yy);
			if(xx<=0)
				xx+=mi[i];//注意出现负数的情况
			y[i]=xx;
		}
		for(i=0;i<n;i++)
			res+=(y[i]*b[i]*M[i]);
		printf("%I64d\n",res%m);
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值