图像分析

3 篇文章 0 订阅
1 篇文章 0 订阅

【简要题意】有n个点,求一条直线穿过至少 n 3 \frac{n}{3} 3n个点。n<=1e6,保证一定存在一条这样的直线。输出穿过任意两点的坐标。

【分析】
思前想后没有办法,结果随机化就a了。。。
考虑最坏的情况:只存在一个 n 3 \frac{n}{3} 3n的点集当中任意两点满足。则每次两点均选中的概率为 1 9 \frac{1}{9} 91。可以循环一百次,一百次后失败的概率为约为 7 1 e 6 \frac{7}{1e6} 1e67。如果你是个非酋,也只能超时一两个点。

【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再乘两次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值