ExCRT

{xa1(modm1)xa2(modm2)xan(modmn)

的一个任意解。

以上是 ExCRT解决的问题。
https://www.luogu.com.cn/problem/P4777


  1. 递归:利用 exgcd 合并 i-1,i 方程
  2. 最后剩下的方程的 an 稍加取模得到答案

如何使用 exgcd 合并方程

{xa1(modm1)xa2(modm2),x=k1m1+a1=k2m2+a2,m1k1m2k2=a2a1.

显然使用 exgcd 求解↑。
k1/k2 回带得 x 的一个任意解。
不难发现通解 xx(modlcm(m1,m2))x 代表特解)。

注意事项

  1. 龟速乘——可能1e18*1e18
  2. 及时取模——模数不同,不能留负数
复制
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n;
pair<int,int>a[N];
int exgcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return a;}
int d=exgcd(b,a%b,x,y),x1=x,y1=y;
x=y1,y=x1-a/b*y1;
return d;
}
int mul(int a,int b,int mod){
int c=0;
while(b){
if(b%2)c=(c+a)%mod;
a=(a+a)%mod,b/=2;
}
return (c+mod)%mod;
}
pair<int,int>work(pair<int,int>a,pair<int,int>b){
pair<int,int>c;
int x,y,A=a.second,B=-b.second,C=b.first-a.first,d=exgcd(A,B,x,y),l=abs(a.second/d*b.second);
if(C%d)return make_pair(-1,-1);
C/=d,x=mul(C,x,l);
return make_pair(((mul(a.second,x,l)+a.first)%l+l)%l,l);
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i].second>>a[i].first;
for(int i=2;i<=n;i++)a[i]=work(a[i-1],a[i]);
cout<<(a[n].first?a[n].first:a[n].second);
}
posted @   pengyule  阅读(103)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示