[NOI2002]荒岛野人

链接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
",i),0;
	return 0;
}

原文地址:https://www.cnblogs.com/Tyher/p/9924619.html