首页 > 代码库 > Finding Lines

Finding Lines

Finding Lines

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4967

概率

在听题解前毫无头绪,题解帮我打开了新世界的大门:

随机取一个点在答案直线(如果存在这个直线)上的概率是p%,

那么随机取到两个点构成的直线就是答案直线的概率是p%*p%;

也就是说,随机取到两个点构成的直线不是答案直线的概率为1-p%*p%<=24/25.

如果我们每次随机取两个点,判定一下这条直线上是否存在p%*n个点,

进行k次后得到错误答案的概率是(1-p%*p%)k.

k取足够大,可以使错误答案的概率趋向于0;当k=100时,错误概率为0.01687.

注意:n<=2时需要特判

代码如下:

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<ctime>
 4 #define N 100005
 5 using namespace std;
 6 typedef long long ll;
 7 struct point{
 8     ll x,y;
 9 }a[N];
10 ll n,p,ans;
11 ll check(ll first,ll second){
12     ll sum=2;
13     ll x1=a[first].x-a[second].x;
14     ll y1=a[first].y-a[second].y;
15     for(int i=0;i<n;++i){
16         if(i==first||i==second)continue;
17         ll x2=a[i].x-a[second].x;
18         ll y2=a[i].y-a[second].y;
19         if(x1*y2-x2*y1==0)sum++;
20     }
21     if(sum*100-p*n>=0)return 1;
22     return 0;
23 }
24 int main(void){
25     while(cin>>n>>p){
26         for(ll i=0;i<n;++i)
27             cin>>a[i].x>>a[i].y;
28         if(n<=2){
29             cout<<"possible\n";
30             continue;
31         }
32         ans=0;
33         srand((int)time(0));
34         for(ll t=0;t<100;++t){
35             ll first=rand()%n,second=rand()%n;
36             if(first==second)continue;
37             ans+=check(first,second);
38         }
39         if(ans)cout<<"possible\n";
40         else cout<<"impossible\n";
41     }
42 }

 

Finding Lines