题目描述
给定 nnn组非负整数 ai,bia_i, b_iai?,bi?,求解关于 xxx的方程组{x≡b1 (mod a1)x≡b2 (mod a2)...x≡bn (mod an)\begin{cases} x \equiv b_1\ ({\rm mod}\ a_1) \\ x\equiv b_2\ ({\rm mod}\ a_2) \\ ... \\ x \equiv b_n\ ({\rm mod}\ a_n)\end{cases}??????????x≡b1? (mod a1?)x≡b2? (mod a2?)...x≡bn? (mod an?)?的最小非负整数解。
输入输出格式
输入格式:
输入第一行包含整数 nnn。
接下来 nnn行,每行两个非负整数 ai,bia_i, b_iai?,bi?。
输出格式:
输出一行,为满足条件的最小非负整数 xxx。
输入输出样例
输入样例#1:
复制
3 11 6 25 9 33 17
输出样例#1: 复制
809
说明
n≤105,1≤ai≤1012,0≤bi≤1012,bi<ain \leq 10^5, 1 \leq a_i \leq 10^{12}, 0 \leq b_i \leq 10^{12}, b_i < a_in≤105,1≤ai?≤1012,0≤bi?≤1012,bi?<ai?,保证答案不超过 101810^{18}1018。
请注意程序运行过程中进行乘法运算时结果可能有溢出的风险。
数据保证有解
#include<iostream> #include<cstring> #include<string> #include<cmath> #include<stdio.h> using namespace std; typedef long long ll; const int maxn=100010; ll a[maxn],b[maxn],n; ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0){ x=1,y=0; return a; } else{ ll d=exgcd(b,a%b,y,x); y-=a/b*x; return d; } } ll quickmul(ll a,ll b,ll mod) { ll ans=0; while(b){ if(b&1)ans=(ans+a)%mod; a=(a+a)%mod; b>>=1; } return ans; } ll solve() { ll M=b[1]; ll ans=a[1]; for(int i=2;i<=n;i++){ ll x,y; ll g=exgcd(M,b[i],x,y); ll c=((a[i]-ans)%b[i]+b[i])%b[i];//将其变正 x=quickmul(x,c/g,b[i]); b[i]/=g; ans+=x*M; M*=b[i]; ans=(ans%M+M)%M; } return ans; } int main() { scanf("%lld",&n); for(int i=1;i<=n;i++)cin>>b[i]>>a[i];//这里为了习惯,反过来输入了 printf("%lld\n",solve()); return 0; }
原文地址:https://www.cnblogs.com/cherish-lin/p/11134606.html
时间: 2024-10-03 02:32:29