中国剩余定理 - 曹冲养猪 - 洛谷 P1495

中国剩余定理 - 曹冲养猪 - 洛谷 P1495

自从曹冲搞定了大象以后,曹操就开始琢磨让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲很不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。

举个例子,假如有 16 头母猪,如果建了 3 个猪圈,剩下 1 头猪就没有地方安家了;如果建造了 5 个猪圈,但是仍然有 1 头猪没有地方去;如果建造了 7 个猪圈,还有 2 头没有地方去。

你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?

输入格式

第一行包含一个整数 n,表示建立猪圈的次数;

接下来 n 行,每行两个整数 ai,bi,表示建立了 ai 个猪圈,有 bi 头猪没有去处。

你可以假定 ai,aj 互质。

输出格式

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

数据范围

1 ≤ n ≤ 10 , 1 ≤ b i ≤ a i ≤ 1100000 , 所 有 a i 的 乘 积 不 超 过 1 0 18 1≤n≤10, 1≤b_i≤a_i≤1100000 ,所有a_i的乘积不超过 10^{18} 1n10,1biai1100000ai1018

输入样例:

3
3 1
5 1
7 2

输出样例:

16

分析:

《中国剩余定理》

本题中:

给 定 n 个 条 件 可 列 出 n 个 方 程 : 给定n个条件可列出n个方程: nn

{ x ≡ b 1 ( m o d   a 1 ) x ≡ b 2 ( m o d   a 2 ) . . . x ≡ b n ( m o d   a n ) , 且 对 任 意 的 i , j ∈ [ 1 , n ] , a i 与 a j 互 质 。 \begin{cases}x≡b_1(mod\ a_1)\\x≡b_2(mod\ a_2)\\...\\x≡b_n(mod\ a_n)\end{cases},且对任意的i,j∈[1,n],a_i与a_j互质。 xb1(mod a1)xb2(mod a2)...xbn(mod an)i,j[1,n]aiaj

即 求 x 的 最 小 正 整 数 解 。 即求x的最小正整数解。 x

满 足 中 国 剩 余 定 理 使 用 的 前 提 条 件 , 满足中国剩余定理使用的前提条件, 使

通 解 : 通解:

x = b 1 M 1 M 1 − 1 + b 2 M 2 M 2 − 1 + . . . + b n M n M n − 1 + k M , x=b_1M_1M_1^{-1}+b_2M_2M_2^{-1}+...+b_nM_nM_n^{-1}+kM, x=b1M1M11+b2M2M21+...+bnMnMn1+kM,

其 中 M = ∏ i = 1 n a i , M i = M a i , M i − 1 是 M i 模 a i 的 逆 元 , k ∈ Z 。 其中M=\prod_{i=1}^na_i,M_i=\frac{M}{a_i},M_i^{-1}是M_i模a_i的逆元,k∈Z 。 M=i=1naiMi=aiMMi1MiaikZ

求 M i − 1 : 解 同 余 方 程 M i x ≡ 1 ( m o d   a i ) < = > M i x + a i y = 1 求M_i^{-1}:解同余方程M_ix≡1(mod\ a_i)\quad<=>\quad M_ix+a_iy=1 Mi1Mix1(mod ai)<=>Mix+aiy=1

扩 展 欧 几 里 得 算 法 解 得 x 0 = M i − 1 扩展欧几里得算法解得x_0=M_i^{-1} x0=Mi1

最 后 要 求 最 小 正 整 数 解 , 即 将 x 对 M 取 模 , 计 算 最 小 正 余 数 。 最后要求最小正整数解,即将x对M取模,计算最小正余数。 xM

代码:

#include
#include
#include

#define ll long long

using namespace std;

int n;
ll A[15],B[15];

void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b) x=1,y=0;
    else
    {
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}

int main()
{
    cin>>n;
    
    ll M=1;
    for(int i=0;i<n;i++)
    {
        cin>>A[i]>>B[i];
        M*=A[i];
    }
    
    ll res=0;
    for(int i=0;i<n;i++)
    {
        ll Mi=M/A[i];
        ll ti,x;
        exgcd(Mi,A[i],ti,x);
        res+=B[i]*Mi*ti;
    }
    
    cout<<(res%M+M)%M<<endl;
    
    return 0;
}

你可能感兴趣的:(数论)