2014-2015 Northwestern European Regional Contest (NWERC 2014) Problem F Finding Lines

只有pdf题面,放个比赛链接http://codeforces.com/gym/101482

题目大意:给n个点,一个p,问是否存在一条直线,让至少 ceil(n * p / 100) 个点在这条直线上。

n <= 1e5,  20 <= p <= 100

解题思路:因为p >= 20,那么如果要达到目标的话,这条线上至少有n/5个点,那么我们现在来选一对点,选中一个的概率1/5,

两个就是1/25,相应的选不中的概率就是24/25,那么我们随机选取两个点,循环一个较多的次数(1000足矣),那么,如果答案存在的话,我们选不中的概率就非常非常小了。

为什么非常小

(1 - 1 / n) ^ n,n趋近于正无穷,这个式子的极限为e。那么对于24/25,我们取一个25 * k次方,对应的值也就接近于e ^ (-k),把k设定到30,这个值已经非常非常小了,不用担心WA了。

这题主要是rand()生成的随机数最多只有3e4,小于题目给的1e5,所以得用其他的随机数生成方法。

AC Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = 7901;
const int maxn = (int)1e5 + 5;
using namespace std;

pair<int, int> a[maxn];

int32_t main()
{
        random_device rd;
	int n, p; scanf("%lld %lld", &n, &p);
	for(int i = 0; i < n; i++){
		scanf("%d %d", &a[i].fi, &a[i].se);
	}
	if(n <= 2) return 0 * puts("possible");
	int Min = ceil(1.0 * n * p / 100.0);
	for(int i = 1; i <= 1000; i++){
		int P1 = rd() % n, P2 = rd() % n;
		while(P1 == P2){
			P2 = rd() % n;
		}
		int x1 = a[P1].fi, y1 = a[P1].se, x2 = a[P2].fi, y2 = a[P2].se;
		int ans = 2;
		for(int j = 0; j < n; j++){
			if(j == P1 || j == P2) continue;
			ll x = a[j].fi, y = a[j].se;
			if((y - y2) * (x2 - x1) == (y2 - y1) * (x - x2)) ans++;
		}
		if(ans >= Min) return 0 * puts("possible");
	}
	puts("impossible");
	return 0;
}

over

猜你喜欢

转载自blog.csdn.net/swunHJ/article/details/82845049