题意:
给你n个点,问你有没有一条直线,经过这n个点里的m个点,使得m/n>=x,
解析:
从1...n里面随机(rand()%n+1)取两个点,那么直线就确定了,
然后再扫一遍n个点,计算这条直线的贡献,如果满足条件则输出Yes
这个过程好像只要随机250次就能在1e4个点中找到答案,好像有些随机1000次的也能在5s之内过
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
typedef pair<ll,ll> PLL;
const int N = 1e4+10;
PLL f[N];
int cross(PLL x,PLL y)
{
return x.fi*y.se-x.se*y.fi;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
double x;
scanf("%d%lf",&n,&x);
int jie=ceil(n*x);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&f[i].fi,&f[i].se);
}
int flag=0;
for(int i=0;i<250;i++)
{
int a=rand()%n+1;
int b=rand()%n+1;
if(f[a].fi==f[b].fi&&f[a].se==f[b].se)
{
continue;
}
int sum=2;
PLL now;
now.fi=f[a].fi-f[b].fi;
now.se=f[a].se-f[b].se;
for(int j=1;j<=n;j++)
{
if(j==a||j==b) continue;
PLL nex;
nex.fi=f[a].fi-f[j].fi;
nex.se=f[a].se-f[j].se;
if(cross(now,nex)==0) sum++;
}
if(sum>=jie) {flag=1;break;}
}
if(flag) printf("Yes\n");
else printf("No\n");
}
}