luogu P2421 [NOI2002]荒岛野人
题目链接
题解
枚举m,然后枚举野人两两检验
感觉复杂度有点高,其实是可以过得....
对野人连立同余式有,c[i]+xp[i]=c[j]+xp[j] (mod m)
移项合并可以exgcd求解x
若x满足生命期限,则m是不行的
代码
#include<cstdio>
#include<algorithm>
inline int read() {
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x;
}
const int maxn = 1000007;
int A,B;
void exgcd(int a,int b,int &x,int &y) {
if(!b) {x = 1,y = 0;return ;}
exgcd(b,a % b,x,y);
int t = x;x = y;y = t - (a / b) * y;
}
int gcd(int x,int y) {return y == 0 ? x : gcd(y,x % y); }
int p[maxn],c[maxn],l[maxn],n;
bool check(int X) {
for(int i = 1;i <= n;++ i) {
for(int j = i + 1;j <= n;++ j) {
int a = X;
int b = p[j] - p[i],C = c[i] - c[j];
int g = gcd(a,b);
if(C % g == 0) {
a /= g,b /= g,C /= g;
int x,y;
exgcd(b,a,x,y);
a = std::abs(a);
x = ((x * C) % a + a) % a;
if(!x) x += a;
if(x <= std::min(l[i],l[j])) return true;
}
}
}
return false;
}
int main() {
n = read();int mx = 0;
for(int i = 1;i <= n;++ i) {
c[i] = read();
p[i] = read();
l[i] = read();
mx = std::max(mx,c[i]) ;
}
for(int i = mx;;++ i) {
//bool flag = 0;
if(!check(i)) {
printf("%d\n",i);
break;
}
}
return 0;
}