描述
自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。举个例子,假如有16头母猪,如果建了3个猪圈,剩下1头猪就没有地方安家了。如果建造了5个猪圈,但是仍然有1头猪没有地方去,然后如果建造了7个猪圈,还有2头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?
格式
输入格式
第一行包含一个整数n (n <= 10) – 建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示建立了ai个猪圈,有bi头猪没有去处。
//你可以假定ai,aj互质.
输出格式
输出包含一个正整数,即为曹冲至少养母猪的数目。
样例1
样例输入1
3
3 1
5 1
7 2
样例输出1
16
sol:孙子定理,挺容易理解的吧。。。
给你n个数A[i],B[i],求出一个数N满足 ∑ N%A[i]=B[i]
要用到中国剩余定理(孙子定理),首先定义一个Mod=∏A[i]
对于当前一个A[i],定义一个P=Mod/A[i]
因为Ai和Aj两两互质,所以P一定与Ai互质
此时的P%其他Aj都是0,所以可以放心使用
暴力的方法就是一句while
ll Sum=P; while(Sum%A[i]!=1) { Sum+=P; }
这肯定会T出屎来,观察式子可得如下的过程
k*P%A[i] = 1
k*P = 1+kk*A[i]
k*P+kk*A[i] = 1 (类似ax+by=c的形式)
同时因为Ai和P互质,gcd=1,而且求通解的公式中的b/gcd变成了b
然后求出Ecgcd中的X后,放心的把ans+=X*P*B[i],因为这个数%其他Aj都是0嘛
还有全部加起来可能会爆long long,需要模一个数,这个数就是前面的 Mod=∏A[i]
因为Mod%所有Ai都为0,这就是为什么我要把变量名叫做Mod的原因了
#include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=‘ ‘; while(!isdigit(ch)) { f|=(ch==‘-‘); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar(‘-‘); x=-x; } if(x<10) { putchar(x+‘0‘); return; } write(x/10); putchar((x%10)+‘0‘); return; } #define W(x) write(x),putchar(‘ ‘) #define Wl(x) write(x),putchar(‘\n‘) ll n; ll A[15],B[15]; inline void Exgcd(ll a,ll b,ll &X,ll &Y) { if(b==0) { X=1; Y=0; return; } Exgcd(b,a%b,X,Y); ll XX=X,YY=Y; X=YY; Y=XX-a/b*YY; return; } inline ll gcd(ll x,ll y) { return (!y)?(x):(gcd(y,x%y)); } int main() { int i; ll Mod=1,ans=0; R(n); for(i=1;i<=n;i++) { Mod*=(A[i]=read()); R(B[i]); } for(i=1;i<=n;i++) { ll P=Mod/A[i]; /* k*P%A[i] = 1 k*P = 1+kk*A[i] k*P+kk*A[i] = 1 (类似ax+by=c的形式) */ ll a=P,b=A[i],c=1; ll X,Y; Exgcd(a,b,X=0,Y=0); ll tmp=b; X=(X>=0)?(X%tmp):(X%tmp+tmp); ans=(ans+X*P*B[i]%Mod)%Mod; } Wl(ans); return 0; } /* input 3 3 1 5 1 7 2 output 16 input 2 99982 19823 99983 92834 output 2696734327 */