excrt

摘自蓝书

考虑使用数学归纳法,假设已经求出了前 k1 个方程构成的方程组的一个解 x。记 m=lcm(m1,m2,...,mk1),则 x+im(iZ) 是前面方程组的一个通解。

简单证明下。

xai(modmi)

因为有

mi|m

所以

x+imai(modmi)

考虑第 k 个方程,求出一个整数 t,使得 x+tmak(modmk)。exgcd 直接做就好了,注意要求出 x 的最小解(https://www.luogu.com.cn/blog/McHf/p5656-exgcd)

#include <bits/stdc++.h> #define int __int128 #define pb push_back using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } void pr(int x) { if(x<0) {putchar('-');x=-x;} if(x>9) pr(x/10); putchar(x%10+'0'); } const int N=(int)(1e5+5); int A[N],m[N],n,x,y; void exgcd(int a,int b) { if(!b) { x=1; y=0; return ; } exgcd(b,a%b); int x1=0,y1=0; x1=y; y1=x-(a/b)*y; x=x1; y=y1; } inline int lcm(int x,int y) { return x/__gcd(x,y)*y; } signed main() { cin.tie(0); ios::sync_with_stdio(false); n=rd(); for(int i=1;i<=n;i++) m[i]=rd(),A[i]=rd(); int ans=A[1],M=m[1]; bool fl=1; for(int i=2;i<=n;i++) { int a=M,b=m[i],C=(A[i]-ans%b+b)%b; int d=__gcd(a,b); if(C%d) { fl=0; break ; } exgcd(M,m[i]); x=x*(C/d)%(m[i]/d); ans+=x*M; M=lcm(M,b); ans=(ans%M+M)%M; } pr((ans%M+M)%M); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16454937.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示