题目:LOJ10215
解析:
扩展欧几里得。
题目就是要求解:
c
[
i
]
+
k
∗
p
[
i
]
≡
c
[
j
]
+
k
∗
p
[
j
]
(
m
o
d
M
)
c[i]+k*p[i]\equiv c[j]+k*p[j](modM)
c[i]+k∗p[i]≡c[j]+k∗p[j](modM)
转化一下:
a
∗
(
p
[
i
]
−
p
[
j
]
)
−
b
∗
m
≡
c
[
j
]
−
c
[
i
]
(
m
o
d
M
)
a*(p[i]-p[j])-b*m\equiv c[j]-c[i](modM)
a∗(p[i]−p[j])−b∗m≡c[j]−c[i](modM)
于是用扩展欧几里得解最小
a
a
a,若无解或
a
≥
m
i
n
(
l
[
i
]
,
l
[
j
]
)
a\geq min(l[i],l[j])
a≥min(l[i],l[j]),则满足题意
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=20;
int n,m,x,y,mx,ans;
int c[Max],p[Max],l[Max];
inline void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d%d",&c[i],&p[i],&l[i]),mx=max(mx,c[i]);
}
inline int GCD(int a,int b){return !b?a:GCD(b,a%b);}
inline void exgcd(int a,int b)
{
if(!b) x=1,y=0;
else
{
exgcd(b,a%b);
int t=x;
x=y,y=t-a/b*x;
}
}
inline bool check(int mid)
{
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
{
int gcd=GCD(p[i]-p[j],mid);
if((c[j]-c[i])%gcd) continue;
int a=(p[i]-p[j])/gcd,b=mid/gcd;
exgcd(a,b),b=abs(b); //注意abs
x=(x*(c[j]-c[i])/gcd%b+b)%b;
if(!x) x+=b; // 注意
if(x<=min(l[i],l[j])) return 0;
}
return 1;
}
inline void solve()
{
for(int i=mx;;i++) if(check(i)) {ans=i;break;}
cout<<ans;
}
int main()
{
init();
solve();
return 0;
}