Description
小明有n個長度不一的小木棍,這些木棍的長度都是正整數。小明的父親想和小明做一個遊戲。他規定一個整數長度l,讓小明閉着眼睛從n個木棍中隨便拿出兩個。如果兩個木棍的長度總和小於等於l,則小明勝,否則小明的父親勝。小明想知道他勝出的概率究竟有多大。
Input
輸入包含兩行。第一行爲兩個整數n和l,其中n和l都不超過100000。第二行包含n個整數,分別爲n個木棍的長度。
Output
輸出包含一個實數,小明勝出的概率,保留兩位小數。
Sample Input
4 5
1 2 3 4
Sample Output
0.67
看看數據範圍發現(n^2)/2算法是過不了的..
其實這道題就是一個水水的加法原理,先排序,插入i=1,j=n兩根指針,若a[i]+a[j]<=l,則從i->中間的所有數+a[i]都是符合要求的,首指針+1,否則把尾指針-1,加一個統計就好了。
這裏我把時間複雜度減了一點,沒有讓i-->n,j-->1,而只是讓i-->j,那麼總的可能性就是高斯求和了。
注意數據範圍,可能int溢出了,一怒之下直接把int替換成long long 了,所以不大美觀。
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
long long n,l,a[1000005]={0},cnt=0;
int main(){
scanf("%d%d",&n,&l);
for(long long i=1;i<=n;i++)scanf("%d",a+i);
sort(a+1,a+n+1);
long long i=1,j=n;
while(i<j)
{
if(a[i]+a[j]<=l)
{
cnt+=j-i;
i++;
}
else j--;
}
long long total_possibilities=n*(n-1)/2;
printf("%.2lf",(double)cnt/total_possibilities);
return 0;
}