【hihocoder 1303】模线性方程组
【题目链接】:http://hihocoder.com/problemset/problem/1303
【题意】
【题解】
/*
x % m[1] = r[1]
x % m[2] = r[2]
x = k[1]*m[1]+r[1] ···①
x = k[2]*m[2]+r[2] ···②
k[1]*m[1]+r[1]=k[2]*m[2]+r[2]
m[1]*k[1]-m[2]*k[2]=r[2]-r[1]
令A=m[1],B=m[2],C=r[2]-r[1],x=k[1],y = -k[2];
A*x+B*y=C
令t = gcd(A,B)
如果C%t!=0则无解
令A'=A/t,B'=B/t,C'=C/t
A'*x+B'y=C'
对于A'x+B‘y=1
求出x0,然后乘上C;
就是A'x+B'y=C'的一个特解了
x0 = x0*C;
然后这个时候x0可能为负值吧;
所以求最小的正值;
x0 = (x0%B'+B')%B';
就能算出来k[1],也即k[1]=x0,;
带回①式
x0= x0*m[1]+r[1]
将x0作为特解;
得到一个解系
x = x0+t*lcm(m[1],m[2]);
这样就相当于得到一个新的方程
X % lcm(m[1],m[2]) == x0
令M = lcm(m[1], m[2]), R = x0,则有新的模方程X mod M = R。
此时,可以发现我们将x mod m[1] = r[1],x mod m[2] = r[2]
合并为了一个式子X mod lcm(m[1], m[2]) = x。满足后者的X一定
满足前两个式子。
这里x0也取最小的正值吧
x0 = x0%lcm(m[1],m[2]);
if (x0<lcm(m[1],m[2])) x0+=lcm(m[1],m[2]);
如果再有一个方程
X % m[3] = r[3]
则可以再用相同的方法求出它的解系
最后输出那个x0就好了
*/
【Number Of WA】
2
【完整代码】
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 110;
int n;
LL m1,r1,m2,r2;
LL gcd(LL a,LL b)
{
if (b==0)
return a;
else
return gcd(b,a%b);
}
void ex_gcd(LL a,LL b,LL &x,LL &y)
{
if (b==0)
{
x = 1,y = 0;
return;
}
ex_gcd(b,a%b,y,x);
y-=a/b*x;
}
int main()
{
//freopen("F:\\rush.txt","r",stdin);
ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf not use
cin >> n;
cin >> m1 >> r1;
rep1(i,2,n)
{
cin >> m2 >> r2;
LL A = m1,B = m2,C = r2-r1;
LL t = gcd(m1,m2);
if (C%t!=0) return cout << -1 << endl,0;
A/=t,B/=t,C/=t;
LL x0,temp;
ex_gcd(A,B,x0,temp);
x0=(C*x0%B+B)%B;//求出A'x+B'y=C'的最小的正值特解
x0 = x0*m1+r1;//x0=k[1],回带出模线性方程组的特解
LL lcm = m1/t*m2;
x0 = x0%lcm;
if (x0<0) x0+=lcm;//求出特解里面的最小正值
m1 = lcm,r1 = x0;
if (i==n) cout << x0 << endl;
}
return 0;
}