1. 程式人生 > >[NOI2002]荒島野人

[NOI2002]荒島野人

for www. 註意 題目 spl fine clu continue play

鏈接P2421 [NOI2002]荒島野人

  • 註意到答案不大於 \(10^6\),考慮從小到大枚舉答案。
  • 對於枚舉的一個答案 \(ans\),我們希望對於每個滿足 \[c_i+k×p_i≡c_j+k×p_j(mod\ ans)\]\(k\) ,都要 \(k > l\)
  • 直接帶入同余方程,於是式子就愉快的變成了 \(exgcd\) 標準形式。
  • 註意這個\(exgcd\)需要判斷無解的情況,如果無解並不代表不滿足情況,反而是滿足情況。
  • 因為無解就是這倆貨這輩子都碰不上面,顯然合法。
  • 註意在求解\(a*x+b*y=c\)的時候,對於這個題目而言可能存在\(x=0\),那麽就讓\(x=b\)即可。
  • 但是這樣是\(wa\)的。
  • 因為\(gcd(a,b,c)\)可能不為1,所以此時\(x=\frac {b}{gcd}\)
#include<bits/stdc++.h>
#define R register int 
using namespace std;
const int N=101;
int n,Mx;
struct Qs{int c,p,l;}w[N];
int cmp(const Qs &x,const Qs &y){return x.p>y.p;}
int gi(){
    R x=0,k=1;char c=getchar();
    while((c<‘0‘||c>‘9‘)&&c!=‘-‘)c=getchar();
    if(c==‘-‘)k=-1,c=getchar();
    while(c>=‘0‘&&c<=‘9‘)x=(x<<3)+(x<<1)+c-‘0‘,c=getchar();
    return x*k;
}
void exgcd(R a,R b,R c,R &x,R &y){
    if(!b){x=c/a,y=0;return;}
    exgcd(b,a%b,c,y,x),y-=(a/b)*x;
}
int Gcd(R x,R y){return y?Gcd(y,x%y):x;}
int sol(R m){
    R x,y;
    for(R i=1;i<=n;++i)
        for(R j=i+1;j<=n;++j){
            R a=w[i].p-w[j].p,b=m,c=w[j].c-w[i].c,gcd=Gcd(a,b);
            if((c+gcd)%gcd!=0)continue;
            a/=gcd,b/=gcd,c/=gcd;
            exgcd(a,b,c,x,y),x=(x%b+b)%b;if(!x)x=b;
            if(x<=w[i].l&&x<=w[j].l)return 0;
        }
    return 1;
}
int main(){
    n=gi();
    for(R i=1;i<=n;++i)
        w[i].c=gi(),w[i].p=gi(),w[i].l=gi(),Mx=max(Mx,w[i].c);
    sort(w+1,w+n+1,cmp);
    for(R i=Mx;i<=1e6;++i)if(sol(i))return printf("%d\n",i),0;
    return 0;
}

[NOI2002]荒島野人