51nod-1079 中国剩余定理模板(孙子定理)

题目链接
China residual theorem,故函数写为Crt

参考博客

传送门1

传送门2

用处

{ x %   a 1 = p 1 x %   a 2 = p 2 … … x %   a n = p n \begin{cases} x\%\,a_1=p_1\\ x\%\,a_2=p_2\\ ……\\ x\%\,a_n=p_n\\ \end{cases} x%a1=p1x%a2=p2x%an=pn

其中 a 1 , a 2 , … … a n a_1,a_2, ……a_n a1a2an 互质,(注意这个使用条件)求解x。

基础定理

定理1:两个数相加,如果存在一个加数,不能被整数a整除,那么它们的和,就不能被整数a整除。

定理2:两数不能整除,若除数扩大(或缩小)了几倍,而被除数不变,则其商和余数也同时扩大(或缩小)相同的倍数(余数必小于除数)。

算法步骤

(用下面这个样例进行演示)

3
3 2
5 3
14 1

1、求出最小公倍数

lcm=3*5*14=210

2.为每组数(a,b)找到一个基础数满足 (lcm/a)%a=b

(1)210÷3=70

70÷3=33…1,故基础数为70*2=140

(2)210÷5=42

42÷5=8…2

5/2=2……1,当前余数1是要找余数3的因子,故可以溯回了。

则1=5-2 * 2=5-2 *(42-8*5)=-2 * 42+17 * 5 (仔细想一下这个哦​ ​🚡​​)

(这个是不是就是求解ax+by=gcd(a,b),又因为互质故而gcd(a,b)=1, 然后得到ax,再利用定理2,余数1扩大3倍,则被除数也扩大3倍,得到基础数ax*3=42*(-2)*3=-252)

(3)210÷14=15

15÷14=1…1,故基础数为15

总结:故而这一步其实可以用扩展欧几里得完成,在(2)比较明显体现。

3.把得到的基础数加和(注意:基础数不一定就是正数)

140-252+15=-97

4.找到符合条件的最小k值

k=(-97+lcm)%lcm=113

代码

#include<cstdio>
#include<algorithm>
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const int maxn=1e2+10;
void exgcd(ll a,ll b,ll& x,ll& y,ll& g) {
    if(b==0)x=1,y=0,g=a;
    else exgcd(b,a%b,y,x,g),y-=x*(a/b);
}

ll a[maxn],p[maxn];
int n;
// 中国剩余定理China residual theorem
ll Crt() {
    ll lcm=1,ans=0;
    for(int i=1;i<=n;++i)lcm*=a[i];
    for(int i=1;i<=n;++i)
    {
        ll now=lcm/a[i],x,y,g;
        exgcd(now,a[i],x,y,g);
        ans=(ans+now*x*p[i])%lcm;
    }
    return  (ans+lcm)%lcm;
}
int main(void) {
//    freopen("in.text","r",stdin);
        scanf("%d",&n);
        for(ll i=1; i<=n; ++i)scanf("%lld%lld",&a[i],&p[i]);
        printf("%lld\n",Crt());
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是Mally呀!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值