luogu P2421 [NOI2002]荒岛野人

题目链接

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; 
} 


posted @ 2018-06-08 19:33  zzzzx  阅读(155)  评论(0编辑  收藏  举报