P4777 【模板】扩展中国剩余定理(EXCRT)

P4777 【模板】扩展中国剩余定理(EXCRT)

题目描述

给定 n 组非负整数 ai,bi ,求解关于 x 的方程组的最小非负整数解。

{xb1(moda1)xb2(moda2)xbn(modan)

提示

对于 100% 的数据,1n1051bi,ai1012,保证所有 ai 的最小公倍数不超过 1018

请注意程序运行过程中进行乘法运算时结果可能有溢出的风险。

数据保证有解。

说句闲话:

非常好的数学题,使我的大脑旋转。
感觉梦回小学奥数了:有一堆苹果,,3个一组剩1个,5个一组剩3个......

Solution:

先膜亿膜我认为最好的题解,十分美味可口,适合我这样的蒟蒻。

我们先转换一下原方程:

{xb (mod a)xB (mod A)

{x=k×a+bx=K×A+B

ka+b=+KA+B

ak+A(K)=Bb

然后我们就可以用 exgcd 求出
ak+A(K)=gcd(a,A)的一组特解(k0,K0)

然后记 q=Bbgcd(aA)
回代:

a(k0×q)+A(K×q)=gcd(a,A)×Bbgcd(a,A)=Bb

x=ak+b ,所以我们希望最小化 x 就是要最小化 k.

然后 k 的通解:k=k0+t×Agcd(a,A)

所以有:

kmin=k0modAgcd(a,A)

然后这两个方程就被合并为了:

xa×kmin+b (mod lcm(a,A))

至于最后的答案统计嘛:

xa×kmin+b (mod lcm(a,A))

在最后一次 merge 做完之后,a=lcm(a1....an),

所以有:

xa×kmin+b (mod a)

x=atmp+b

那么我们只需要在保证x0的情况下最小化 tmp 就好了,其实就是x=b mod a

然后这题就愉快的做完了。

Code:

#include<bits/stdc++.h>
#define ll __int128
using namespace std;
ll read()
{
ll res=0;char c;
while(c<'0'||'9'<c)c=getchar();
while('0'<=c&&c<='9'){res=res*10+c-'0';c=getchar();}
return res;
}
void exgcd(ll &x,ll &y,ll a,ll b)
{
if(!b)x=1,y=0;
else {exgcd(y,x,b,a%b);y-=a/b*x;}
}
ll gcd(ll x,ll y)
{
return y ? gcd(y,x%y) : x;
}
ll lcm(ll x,ll y)
{
return x/gcd(x,y)*y;
}
ll a,b,A,B,x,y;
void merge()
{
exgcd(x,y,a,A);
ll d=gcd(a,A),mod=lcm(a,A),c=B-b,p=c/d,q=A/d;
if(c%d){cout<<-1;exit(0);}
x=x*p%q;x = x<0 ? x+q : x;
b=(a*x+b)%mod;b = b<0 ? b+mod : b;
a=mod;
}
int n;
void work()
{
cin>>n;
a=read(),b=read();
for(int i=2;i<=n;i++)
{
A=read(),B=read();
merge();
}
long long ans=(long long )(b%a);
cout<<ans;
}
int main()
{
//freopen("excrt.in","r",stdin);freopen("excrt.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示