两种方法解线性同余方程

mac2026-10-02  3

求解线性同余方程

x ≡ r 1 ( m o d   a 1 ) x\equiv r_1(mod\ a_1) x≡r1​(mod a1​)

x ≡ r 2 ( m o d   a 2 ) x\equiv r_2(mod\ a_2) x≡r2​(mod a2​)

… \dots …

x ≡ r k ( m o d   a k ) x\equiv r_k(mod\ a_k) x≡rk​(mod ak​)

方法一: x ≡ r 1 ( m o d   a 1 ) ⟶ x = r 1 + a 1 y 1 x\equiv r_1(mod\ a_1) \longrightarrow x=r_1+a_1y_1 x≡r1​(mod a1​)⟶x=r1​+a1​y1​ x ≡ r 2 ( m o d   a 2 ) ⟶ x = r 2 + a 2 y 2 x\equiv r_2(mod\ a_2) \longrightarrow x=r_2+a_2y_2 x≡r2​(mod a2​)⟶x=r2​+a2​y2​ 联立: a 1 y 1 − a 2 y 2 = r 2 − r 1 a_1y_1-a_2y_2=r_2-r_1 a1​y1​−a2​y2​=r2​−r1​ 求得: y 1 y_1 y1​的一个解 y ′ y' y′, y 1 = y ′ + k a 2 g c d ( a 1 , a 2 ) y_1=y'+k\frac {a_2}{gcd(a_1,a_2)} y1​=y′+kgcd(a1​,a2​)a2​​ 带入原式: x = r 1 + a 1 ( y ′ + k a 2 g c d ( a 1 , a 2 ) ) x=r_1+a_1(y'+k\frac {a_2}{gcd(a_1,a_2)}) x=r1​+a1​(y′+kgcd(a1​,a2​)a2​​) 化简: x = r 1 + a 1 y ′ + k a 1 a 2 g c d ( a 1 , a 2 ) x=r_1+a_1y'+k \frac {a_1a_2}{gcd(a_1,a_2)} x=r1​+a1​y′+kgcd(a1​,a2​)a1​a2​​

再化简得到: x ≡ r 1 + a 1 y ′ ( m o d   a 1 a 2 g c d ( a 1 , a 2 ) ) x\equiv r_1+a_1y'(mod\ \frac {a_1a_2}{gcd(a_1,a_2)}) x≡r1​+a1​y′(mod gcd(a1​,a2​)a1​a2​​) 这样就可以继续与后面的式子联立了

ll solve(ll *a,ll *r,ll n) { ll a1=a[1],r1=r[1]; for(int i=2;i<=n;++i) { ll a2=a[i],r2=r[i]; ll A=a1,B=a2,M=r2-r1,X,Y; ll GCD=exgcd(A,B,X,Y); if(M%GCD!=0) return -1; ll b1=a2/GCD; X=(X*M/GCD%b1+b1)%b1; r1=r1+a1*X; a1=a1*a2/GCD; } return r1; }

方法二:中国剩余定理 假设已经求出了前k-1个方程的解,现在联立第k个求解 L C M = ∏ i = 1 k − 1 a i LCM=\prod_{i=1}^{k-1} a_i LCM=∏i=1k−1​ai​,前面的解为 x k − 1 x_{k-1} xk−1​。我们需要求出 t t t,满足下面的式子 x k − 1 + t × L C M ≡ r k ( m o d   a k ) x_{k-1}+t\times LCM\equiv r_k(mod\ a_k) xk−1​+t×LCM≡rk​(mod ak​) 求出 t t t 之后,得到一个新的解 x k = x k − 1 + t × L C M x_k=x_{k-1}+t\times LCM xk​=xk−1​+t×LCM 把LCM更新后,再取模

ll excrt(ll *a,ll *r,ll n) { ll LCM=a[1],ans=r[1]; for(int i=2;i<=n;i++) { ll A=LCM,B=a[i],M=(r[i]-ans%B+B)%B,X,Y; ll GCD=exgcd(A,B,X,Y); if(M%GCD!=0) return -1; ll b1=B/GCD; X=(X*(M/GCD)%b1+b1)%b1; ans+=X*LCM; LCM*=b1; ans=(ans%LCM+LCM)%LCM; } return ans; }

Strange Way to Express Integers POJ - 2891

#include <iostream> #include <algorithm> #include <cstdio> #define ll long long using namespace std; const int maxn=1e5+5,INF=0x3f3f3f3f; int n; ll a[maxn],r[maxn]; ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) { x=1,y=0; return a; } ll q=exgcd(b,a%b,y,x); y-=a/b*x; return q; } ll excrt(ll *a,ll *r,ll n) { ll LCM=a[1],ans=r[1]; for(int i=2;i<=n;i++) { ll A=LCM,B=a[i],M=(r[i]-ans%B+B)%B,X,Y; ll GCD=exgcd(A,B,X,Y); if(M%GCD!=0) return -1; ll b1=B/GCD; X=(X*(M/GCD)%b1+b1)%b1; ans+=X*LCM; LCM*=b1; ans=(ans%LCM+LCM)%LCM; } return ans; } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;++i) scanf("%lld%lld",&a[i],&r[i]); ll ans=excrt(a,r,n); printf("%lld\n",ans); } return 0; }
最新回复(0)