【簡要題意】有n個點,求一條直線穿過至少個點。n<=1e6,保證一定存在一條這樣的直線。輸出穿過任意兩點的座標。
【分析】
思前想後沒有辦法,結果隨機化就a了。。。
考慮最壞的情況:只存在一個的點集當中任意兩點滿足。則每次兩點均選中的概率爲。可以循環一百次,一百次後失敗的概率爲約爲。如果你是個非酋,也只能超時一兩個點。
【code】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=1e6+1000;
struct node{int x,y;}a[maxn];
int n;
inline void read(int &x){
x=0;int fl=1;char tmp=getchar();
while(tmp<'0'||tmp>'9'){if(tmp=='-')fl=-fl;tmp=getchar();}
while(tmp>='0'&&tmp<='9') x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
x=x*fl;
}
inline int rand(int l,int r){
return 1LL*rand()*rand()%(r-l+1)+l;
}
signed main(){
srand(19260817);
cin>>n;
for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y);
while(1){
int i=rand(1,n),j=rand(1,n);
while(i==j) i=rand(1,n),j=rand(1,n);
int cnt=0;
for(int k=1;k<=n;k++){
if((a[j].x-a[i].x)*(a[k].y-a[i].y)==(a[k].x-a[i].x)*(a[j].y-a[i].y))cnt++;
}
if(cnt*3>=n){
printf("%lld %lld\n",i,j);
return 0;
}
}
return 0;
}
這裏有一個坑點就是,普通評測機下RAND_MAX=32768,但linux下的GCC默認爲maxlongint。所以通用解法還是乘1LL再乘兩次。