洛谷P1495 曹冲养猪

洛谷P1495 曹冲养猪

题目描述

自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。举个例子,假如有16头母猪,如果建了3个猪圈,剩下1头猪就没有地方安家了。如果建造了5个猪圈,但是仍然有1头猪没有地方去,然后如果建造了7个猪圈,还有2头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?

输入输出格式

输入格式:

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

输出格式:

输出包含一个正整数,即为曹冲至少养母猪的数目。

输入输出样例

输入样例#1: 复制
3
3 1
5 1
7 2
输出样例#1: 复制
16

分析

很明显的是中国剩余定理,推荐一篇讲得很好的文章:传送门

为什么中国剩余定理必须模数两两互质呢?因为如果不互质的话就没有逆元了。

为什么用中国剩余定理解是唯一的呢?因为在模意义下一个数要么没有逆元,要么就只有一个逆元。

中国剩余定理对于同与方程组是有限制条件的,如果模数两两不一定互质怎么办?可以利用两两合并的思想,两个两个解。暂且就叫他扩展中国剩余定理吧。

代码

#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\n",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;
}
扩展中国剩余定理

 

posted @ 2017-11-07 21:29  沐灵_hh  阅读(209)  评论(0编辑  收藏  举报