链接:http://poj.org/problem?id=2891
题意:给k对(ai,ri),解模线性方程组 m ≡ ri (mod) ai 判定是否有解,求最小解。
思路:由于这里的ai不满足两两互质,所以不能用孙子定理。
所以就是解一般的模线性方程组。看了解题报告,把每两个方程合并来做。
参考链接:http://www.cnblogs.com/54zyq/articles/3356051.html
这道题我有一个不懂的地方,查了书才明白。
对方程 ax ≡ b (mod) n ,d = gcd(a,n) 若 d | b 则 有 d 个解 ,最小的解为x0 = (x*(b/d) mod n + n )mod(n/d) ,则所有满足方程 x = x0 (mod) (n/d) 的 x 都是原方程的解。
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<cmath> #include<vector> #include<set> #include<map> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long LL; const double PI=acos(-1); const int inf=0x3f3f3f3f; const double eps=1e-10; const int maxn=100000; int k; LL a[maxn],r[maxn]; void egcd(LL a,LL b,LL &d,LL &x,LL &y) { if(!b) { d=a;x=1;y=0; } else { egcd(b,a%b,d,y,x); y-=x*(a/b); } } LL solve() { LL A=a[0],R=r[0],d,x,y; for(int i=1;i<k;i++) { egcd(A,a[i],d,x,y); if((r[i]-R)%d) return -1; x=x*((r[i]-R)/d)%(a[i]/d); //此时新的方程变为:m ≡ x*a1 + r1 mod (lcm(a1,a2)) R+=x*A;//新的r=x*a1+r1 A=A*a[i]/d;//新的A=lcm(a1,a2) R%=A; //缩小一下R的范围 } return R>0?R:R+A; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(~scanf("%d",&k)) { for(int i=0;i<k;i++) scanf("%lld%lld",&a[i],&r[i]); printf("%lld ",solve()); } return 0; }