【NOIP practice】BSOJ 3851 計算概率 智力題——加法原理

3851 -- 【模擬試題】計算概率
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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章