exgcd&&中国剩余定理

拓展欧几里得模板

求 解 g c d ( a , b ) = a ∗ x + b ∗ y , x 与 y 的 值 求解gcd(a,b)=a*x+b*y,x与y的值 gcd(a,b)=ax+byxy
由 g c d ( a , b ) = 由gcd(a,b)= gcd(a,b)= g c d ( b , a gcd(b,a gcd(b,a% b b b ) ) )
a ∗ x + b ∗ y = b ∗ x + ( a − ⌊ a b ⌋ ∗ b ) ∗ y a*x+b*y=b*x+(a-\lfloor\frac{a}{b}\rfloor*b)*y ax+by=bx+(abab)y
a ∗ x + b ∗ y = a ∗ y + b ∗ ( x − a / b ∗ y ) a*x+b*y=a*y+b*(x-a/b*y) ax+by=ay+b(xa/by)
发 现 a ∗ x 对 应 a ∗ y 只 有 一 项 不 相 等 , 直 接 交 换 即 可 发现a*x对应a*y只有一项不相等,直接交换即可 axay
a ∗ x + b ∗ y = a ∗ x + b ∗ ( y − ⌊ a b ⌋ ∗ x ) a*x+b*y=a*x+b*(y-\lfloor\frac{a}{b}\rfloor*x) ax+by=ax+b(ybax)
a*x+b*y=c存在解的充分必要条件c%__gcd(a,b)==0
a ∗ x + b ∗ y = c a*x+b*y=c ax+by=c等价于 a ∗ x ≡ c ( m o d b ) a*x\equiv c\pmod b axc(modb)有解的充分必要条件c%gcd(a,b)=0
例:求解 a ∗ x ≡ 1 ( m o d b ) a*x\equiv1\pmod b ax1(modb)即为: a ∗ x + b ∗ y ≡ 1 ( m o d b ) a*x+b*y\equiv1 \pmod {b} ax+by1(modb)的解
当1%__gcd(a,b)==0时可直接用模板解。

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int d=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}

中国剩余定理

{ x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) . . . x ≡ a n ( m o d m n ) ( m 1 . . . m n 两 两 互 质 ) \left\{ \begin{aligned} x\equiv a_1 \pmod {m_1}\\ x\equiv a_2 \pmod {m_2}\\ ...\\ x\equiv a_n \pmod {m_n} \end{aligned} \right.(m_1...m_n两两互质) xa1(modm1)xa2(modm2)...xan(modmn)(m1...mn)
M = ∏ i = 1 n m i , t k M=\prod_{i=1}^{n}m_i,t_k M=i=1nmitk M m k ∗ t k ≡ 1 ( m o d m k ) \frac{M}{m_k}*t_k\equiv1\pmod {m_k} mkMtk1(modmk)的最小非负整数解
其中 ∀ i ! = k M m i ∗ t i ≡ 0 ( m o d m i ) \forall {_{i!=k}}\frac{M}{m_i}*t_i\equiv0 \pmod {m_i} i!=kmiMti0(modmi)
两边 ∗ a [ i ] *a[i] a[i]
{ a k ∗ M m k ∗ t i ≡ a k ( m o d m k ) ∀ i ! = k a i ∗ M m k ∗ t i ≡ 0 ( m o d m i ) \left\{ \begin{aligned} a_k*\frac{M}{m_k}*t_i\equiv a_k\pmod {m_k}\\ \forall{_{i!=k}}a_i*\frac{M}{m_k}*t_i\equiv 0 \pmod {m_i} \end{aligned} \right. akmkMtiak(modmk)i!=kaimkMti0(modmi)
则有一个解为 x = ∑ i = 1 n a i ∗ M m i ∗ t i x=\sum_{i=1}^{n}a_i*\frac{M}{m_i}*t_i x=i=1naimiMti
通解为 x + k ∗ M ( k ∈ Z ) x+k*M(k\in Z) x+kM(kZ)
P3868 [TJOI2009] 猜数字

#include <iostream>
using namespace std;
using ll = long long ;
int n;
ll read(){
    char ch=getchar();
    int f=1;
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    ll x=0;
    while(isdigit(ch)){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return f*x;
}
ll a[20],b[20];
ll mul(ll a,ll b,ll p){///龟速乘
    ll r=0;
    while(b){
        if(1&b)r=(r+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return r;
}
/**
    gcd(a,b)=gcd(b,a%b)
    a*x+b*y=b*x+(a-a/b*b)*y
    a*x+b*y=a*y+b*(x-a/b*y)
*/
void exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1,y=0;
        return ;
    }
    exgcd(b,a%b,y,x);
    y-=a/b*x;
}
ll china(){
    ll M=1;
    for(int i=1;i<=n;i++) M*=b[i];
    ll ans=0;
    ll x,y;
    for(int i=1;i<=n;i++)
    {
        ll tp=M/b[i];
        exgcd(tp,b[i],x,y);
        x=(x%b[i]+b[i])%b[i];
        ans=(ans+mul(mul(tp,x,M),a[i],M))%M;
    }
    return (ans+M)%M;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++) b[i]=read(),a[i]=(a[i]%b[i]+b[i])%b[i];
    printf("%lld",china());
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

倾海、

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

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

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

打赏作者

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

抵扣说明:

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

余额充值