poj 2891
轉載:
/**********************一般模線性方程組***********************/
同樣是求這個東西。。
X mod m1=r1
X mod m2=r2
...
...
...
X mod mn=rn
首先,我們看兩個式子的情況
X mod m1=r1……………………………………………………………(1)
X mod m2=r2……………………………………………………………(2)
則有?
X=m1*k1+r1………………………………………………………………(*)
X=m2*k2+r2
那么 m1*k1+r1=m2*k2+r2
整理,得
m1*k1-m2*k2=r2-r1
令(a,b,x,y,m)=(m1,m2,k1,k2,r2-r1),原式變成
ax+by=m
熟悉吧?
此時,因為GCD(a,b)=1不一定成立,GCD(a,b) | m 也就不一定成立。所以應該先判 若 GCD(a,b) | m 不成立,則!!!方程無解!!!。
否則,繼續往下。
解出(x,y),將k1=x反代回(*),得到X。
于是X就是這兩個方程的一個特解,通解就是 X'=X+k*LCM(m1,m2)
這個式子再一變形,得 X' mod LCM(m1,m2)=X
這個方程一出來,說明我們實現了(1)(2)兩個方程的合并。
令 M=LCM(m1,m2),R=r2-r1
就可將合并后的方程記為 X mod M = R。
然后,擴展到n個方程。
用合并后的方程再來和其他的方程按這樣的方式進行合并,最后就能只剩下一個方程 X mod M=R,其中 M=LCM(m1,m2,...,mn)。
那么,X便是原模線性方程組的一個特解,通解為 X'=X+k*M。
如果,要得到X的最小正整數解,就還是原來那個方法:
X%=M;
if (X<0) X+=M;
#include <iostream> #include <cstdio> #include<cmath> #include<algorithm> #include<cstdlib> #define max 100000 using namespace std; long long ex_gcd(long long a,long long b,long long &x,long long &y) {if(!b){x=1;y=0;return a;}int d=ex_gcd(b,a%b,x,y);int t=x;x=y;y=t-a/b*y;return d; } long long ex_crl(long long *w,long long *a,long long n) {long long m=w[0],r=a[0];long long x,y;for(int i=1;i<n;++i){long long d=ex_gcd(m,w[i],x,y);if((a[i]-r)%d)return -1;long long t=(w[i]/d);x=(x*((a[i]-r)/d)%t+t)%t;//最小正整數解r+=x*m;//特解m=m*w[i]/d;//lcmr%=m;//特解%lcm}if(r<0)r+=m;return r; } int main() {int n;while(cin>>n){long long w[max],a[max];for(int i=0;i<n;++i)cin>>w[i]>>a[i];cout<<ex_crl(w,a,n)<<endl;}return 0; }
總結
- 上一篇: hdu 1576
- 下一篇: poj 2392 dp 不是很懂哎!!!