洛谷P1495 曹冲养猪
题目描述
自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。举个例子,假如有16头母猪,如果建了3个猪圈,剩下1头猪就没有地方安家了。如果建造了5个猪圈,但是仍然有1头猪没有地方去,然后如果建造了7个猪圈,还有2头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?
输入输出格式
输入格式:
第一行包含一个整数n (n <= 10) – 建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示建立了ai个猪圈,有bi头猪没有去处。你可以假定ai,aj互质.
输出格式:
输出包含一个正整数,即为曹冲至少养母猪的数目。
输入输出样例
分析
很明显的是中国剩余定理,推荐一篇讲得很好的文章:传送门。
为什么中国剩余定理必须模数两两互质呢?因为如果不互质的话就没有逆元了。
为什么用中国剩余定理解是唯一的呢?因为在模意义下一个数要么没有逆元,要么就只有一个逆元。
中国剩余定理对于同与方程组是有限制条件的,如果模数两两不一定互质怎么办?可以利用两两合并的思想,两个两个解。暂且就叫他扩展中国剩余定理吧。
代码
#include<cstdio> using namespace std; typedef long long ll; ll n,x,y,a[12],m[12]; void exgcd(ll a,ll b,ll &x,ll &y){ if(!b){x=1;y=0;return;} exgcd(b,a%b,y,x); y-=(a/b)*x; } inline ll inv(ll a,ll b){ exgcd(a,b,x,y); return (x%b+b)%b; } ll china(){ ll M=1,res=0; for(int i=1;i<=n;++i) M*=m[i]; for(int i=1;i<=n;++i){ ll w=M/m[i]; res=(res+inv(w,m[i])*w*a[i])%M; } return (res+M)%M; } int main(){ scanf("%lld",&n); for(int i=1;i<=n;++i) scanf("%lld%lld",&m[i],&a[i]); printf("%lld ",china()); return 0; }
#include<cstdio> using namespace std; typedef long long ll; ll n,a1,m1,a2,m2,x,y,c,d; void exgcd(ll a,ll b,ll &x,ll &y){ if(!b){d=a; x=1;y=0;return;} exgcd(b,a%b,y,x); y-=(a/b)*x; } int main(){ scanf("%lld",&n); scanf("%lld%lld",&m1,&a1); for(int i=2;i<=n;++i){ scanf("%lld%lld",&m2,&a2); ll c=a2-a1,a=m1,b=m2; exgcd(a,b,x,y); x=(x*(c/d)%(b/d)+(b/d))%(b/d); a1=m1*x+a1; m1=m1/d*m2; } printf("%lld",a1); return 0; }