同餘方程
阿新 • • 發佈:2021-10-10
問題描述
方程組:
\(x \equiv a_1 ( mod\:m_1)\)
\(x \equiv a_2(mod\:m_2)\)
····
\(x \equiv a_k(mod\: m_k)\)
求解x
求解
首先考慮前兩個式子
\(x=m_1\cdot y_1+a_1=m_2\cdot y_2+a_2\)
則\(m_1y_1-m_2y_2=a_2-a_1\)(有解當且僅當\((m_1,m_2)|a_2-a_1)\)
\(y_1=y_0+\frac{km_2}{(m_1,m_2)}(k\in Z)\)
則\(x=m_1y_0+\frac{km_1m_2}{(m_1,m_2)}+a_1\),設\(x'=m_1y_0+a_1\)
則\(x=x'+k[m_1,m_2] ([m_1,m_2]為最小公倍數)\)
所以得到新的式子\(x\equiv x'(mod \:[m_1m_2])\)
則原來方程組方程數目減一
以此類推,得到\(x\equiv x'' (mod \:[m_1m_2m_3])\)
繼續下去便得到x的解
poj2891 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=10000000+101; inline ll read(){ ll x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } int k; void exgcd(ll a,ll b,ll &d,ll &x,ll &y){ if(!b){d=a;x=1;y=0;return ;} exgcd(b,a%b,d,x,y); ll t=x;x=y;y=t-(a/b)*y; return ; } int main(){ while(scanf("%d",&k)!=EOF){ ll a1=read(),r1=read(),a2,r2; bool fa=false; for(int i=2;i<=k;i++){ a2=read();r2=read(); if(fa)continue; ll d,x,y,c=r1-r2; exgcd(a2,a1,d,x,y); if(c%d){fa=true;continue;} x=x*(c/d); a1/=d; x=(x%a1+a1)%a1;//求最小整數解 x=(x*a2+r2); a1=a1*a2; r1=((x%a1)+a1)%a1; } if(fa)printf("-1\n"); else printf("%lld\n",r1); } return 0; }