Finding Lines
概率
在听题解前毫无头绪,题解帮我打开了新世界的大门:
随机取一个点在答案直线(如果存在这个直线)上的概率是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 "; 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 "; 40 else cout<<"impossible "; 41 } 42 }