正题
题目链接:https://www.luogu.org/problem/P4777
题目大意
求方程
{x≡a1(modb1)x≡a2(modb2)...x≡an(modbn)\begin{cases} x \equiv a_1\ ({\rm mod}\ b_1) \\ x\equiv a_2\ ({\rm mod}\ b_2) \\ ... \\ x \equiv a_n\ ({\rm mod}\ b_n)\end{cases}⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡a1 (mod b1)x≡a2 (mod b2)...x≡an (mod bn)
的解。
解题思路
我们考虑两个两个方程进行合并。
假设现在只有两个方程x≡a1(modb1),x≡a2(modb2)x\equiv a_1(\rm mod\ b_1),x\equiv a_2(\rm mod\ b_2)x≡a1(mod b1),x≡a2(mod b2)
⇒x=a1+k1b1=a2+k2b2\Rightarrow x=a_1+k_1b_1=a_2+k_2b_2⇒x=a1+k1b1=a2+k2b2
⇒k1b1−k2b2=a2−a1\Rightarrow k_1b_1-k_2b_2=a_2-a_1⇒k1b1−k2b2=a2−a1
然后用exgcdexgcdexgcd计算出来后合并成新的式子用于后面的合并。
最后可以将所有的合并成一个,再解它就好了。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+100;
ll n,a[N],b[N],ans;
ll ksc(ll a,ll b,ll YMW)
{a%=YMW;b%=YMW;ll c=(long double)a*b/YMW;ll ans=a*b-c*YMW;if(ans<0) ans+=YMW;else if(ans>=YMW) ans-=YMW;return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{if(!b){x=1;y=0;return a;}ll d=exgcd(b,a%b,x,y),z=x;x=y;y=z-a/b*y;return d;
}
void work()
{ll x,y,k,M=b[1];ans=a[1];for(ll i=2;i<=n;i++){ll A=M,B=b[i],c=(a[i]-ans%B+B)%B;ll d=exgcd(A,B,x,y),g=B/d;if(c%d){ans=-1;return;}x=ksc(x,c/d,g);ans+=x*M;M*=g;ans=(ans%M+M)%M;}
}
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld%lld",&b[i],&a[i]);work();printf("%lld",ans);
}