圖像分析

【簡要題意】有n個點,求一條直線穿過至少n3\frac{n}{3}個點。n<=1e6,保證一定存在一條這樣的直線。輸出穿過任意兩點的座標。

【分析】
思前想後沒有辦法,結果隨機化就a了。。。
考慮最壞的情況:只存在一個n3\frac{n}{3}的點集當中任意兩點滿足。則每次兩點均選中的概率爲19\frac{1}{9}。可以循環一百次,一百次後失敗的概率爲約爲71e6\frac{7}{1e6}。如果你是個非酋,也只能超時一兩個點。

【code】

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=1e6+1000;
struct node{int x,y;}a[maxn];
int n;
inline void read(int &x){
	x=0;int fl=1;char tmp=getchar();
	while(tmp<'0'||tmp>'9'){if(tmp=='-')fl=-fl;tmp=getchar();}
	while(tmp>='0'&&tmp<='9') x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
	x=x*fl;
}
inline int rand(int l,int r){
	return 1LL*rand()*rand()%(r-l+1)+l;
}
signed main(){
	srand(19260817);
	cin>>n;
	for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y);
	while(1){
		int i=rand(1,n),j=rand(1,n);
		while(i==j) i=rand(1,n),j=rand(1,n);
		int cnt=0;
		for(int k=1;k<=n;k++){
			if((a[j].x-a[i].x)*(a[k].y-a[i].y)==(a[k].x-a[i].x)*(a[j].y-a[i].y))cnt++;
		}
		if(cnt*3>=n){
			printf("%lld %lld\n",i,j);
			return 0;
		}
	}
	return 0;
}

這裏有一個坑點就是,普通評測機下RAND_MAX=32768,但linux下的GCC默認爲maxlongint。所以通用解法還是乘1LL再乘兩次。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章