题目描述
给n个点,求是否至少存在(n * p / 100)个点在一条直线上
思路
暴力显然是不可取的,翻阅了题解学习该题,也是第一次接触这样的随机算法。
如果存在一条线满足情况,有m个点在这条直线上,选取任意两个点,选中的一个点的在直线上的概率是
m
n
\frac{m}{n}
nm,选另一个点的恰好也在直线上的概率就是
(
m
−
1
)
n
\frac{(m-1)}{n}
n(m−1),就变成选中这条直线的概率是
m
∗
(
m
−
1
)
n
∗
n
\frac{m*(m-1)}{n * n}
n∗nm∗(m−1),选不中这条直线的概率变成了
t
=
(
1
−
m
∗
(
m
−
1
)
n
∗
n
)
t = (1-\frac{m*(m-1)}{n*n})
t=(1−n∗nm∗(m−1)),然后应该随机选1000次,全部选不中的概率就是t1000,
t
<
1
t <1
t<1,1000次方以后接近于0,就随机枚举1000次了,没有随机取到就impossible
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
struct node {
LL x, y;
}a[N];
int n, p;
void solve() {
for(int i = 1; i <= n; i++) {
scanf("%lld%lld", &a[i].x, &a[i].y);
}
if(n <= 2) {
puts("possible");
return;
}
int t = 1000;
int num = ceil(n * p * 1.0 / 100);
srand(time(0));
while(t--) {
int p1 = (LL)rand() * rand() % n + 1;
int p2 = (LL)rand() * rand() % n + 1;
while(p1 == p2) p2 = rand() % n + 1;
LL x1 = a[p2].x - a[p1].x, y1 = a[p2].y - a[p1].y;
int cnt = 0;
for(int i = 1; i <= n; i++) {
LL x2 = a[i].x - a[p1].x, y2 = a[i].y - a[p1].y;
if(x1 * y2 == x2 * y1) cnt++;
}
if(cnt * 100 >= n * p) {
puts("possible");
return;
}
}
puts("impossible");
}
int main() {
//freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &p))
solve();
return 0;
}