题目

Source

http://acm.hdu.edu.cn/showproblem.php?pid=4609

Description

King OMeGa catched three men who had been streaking in the street. Looking as idiots though, the three men insisted that it was a kind of performance art, and begged the king to free them. Out of hatred to the real idiots, the king wanted to check if they were lying. The three men were sent to the king's forest, and each of them was asked to pick a branch one after another. If the three branches they bring back can form a triangle, their math ability would save them. Otherwise, they would be sent into jail.
However, the three men were exactly idiots, and what they would do is only to pick the branches randomly. Certainly, they couldn't pick the same branch - but the one with the same length as another is available. Given the lengths of all branches in the forest, determine the probability that they would be saved.

Input

An integer T(T≤100) will exist in the first line of input, indicating the number of test cases.
Each test case begins with the number of branches N(3≤N≤105).
The following line contains N integers a_i (1≤a_i≤105), which denotes the length of each branch, respectively.

Output

Output the probability that their branches can form a triangle, in accuracy of 7 decimal places.

Sample Input

2
4
1 3 3 4
4
2 3 3 4

Sample Output

0.5000000
1.0000000

分析

题目大概说,有n条边,长度在[1,100000],从中任选三条边,问组成三角形的概率是多少。

这题思路好绕。

详见:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html

大概这样:

  • 首先求出两两组合成长度和位i的方案数tot[i]
  • 然后从小到大枚举三角形最长的边len,那么现在要确定另外两条边合法组合的方案数

这个方案数为:

Σtot[i](i>len)- 最长边与其他边组合的方案数 - 长度小于最长边与长度大于等于最长边的其他边组合的方案数 - 长度大于等于最长边的其他边之间组合的方案数

Σtot[i]可以通过前缀和差分求得,其他部分简单的组合计算。

而tot[i]如何求?

构造一个多项式,$\sum_ic_ix^i$,表示长度$i$的边有$c_i$个,而$\sum_ic_ix^i \times \sum_ic_ix^i$的结果$\sum_iC_ix^i$就表示有先后顺序且放回地选出两条边长度和为$i$的方案数为$C_i$

这其实是母函数吧。。然后利用FFT去快速求得这个多项式的值。

不过这个多项式求出来还不是最终的,再减去自身与自身组合,最后除以2即是要的tot[i]。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 277777
const double PI=acos(-1.0); struct Complex{
double real,imag;
Complex(double _real,double _imag):real(_real),imag(_imag){}
Complex(){}
Complex operator+(const Complex &cp) const{
return Complex(real+cp.real,imag+cp.imag);
}
Complex operator-(const Complex &cp) const{
return Complex(real-cp.real,imag-cp.imag);
}
Complex operator*(const Complex &cp) const{
return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
}
void setValue(double _real=0,double _imag=0){
real=_real; imag=_imag;
}
}; int len;
Complex wn[MAXN],wn_anti[MAXN]; void FFT(Complex y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
for(int h=2; h<=len; h<<=1){
Complex Wn=(op==1?wn[h]:wn_anti[h]);
for(int i=0; i<len; i+=h){
Complex W(1,0);
for(int j=i; j<i+(h>>1); ++j){
Complex u=y[j],t=W*y[j+(h>>1)];
y[j]=u+t;
y[j+(h>>1)]=u-t;
W=W*Wn;
}
}
}
if(op==-1){
for(int i=0; i<len; ++i) y[i].real/=len;
}
}
void Convolution(Complex A[],Complex B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i].setValue();
B[i].setValue();
}
for(int i=0; i<=len; ++i){
wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
wn_anti[i].setValue(wn[i].real,-wn[i].imag);
}
FFT(A,1); FFT(B,1);
for(int i=0; i<len; ++i){
A[i]=A[i]*B[i];
}
FFT(A,-1);
} Complex A[MAXN],B[MAXN];
int a[111111],cnt[111111];
long long tot[MAXN];
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(cnt,0,sizeof(cnt));
int maxa=0;
for(int i=0; i<n; ++i){
scanf("%d",a+i);
++cnt[a[i]];
maxa=max(maxa,a[i]);
}
for(int i=0; i<=maxa; ++i){
A[i].setValue(cnt[i]);
B[i].setValue(cnt[i]);
}
Convolution(A,B,maxa+1);
for(int i=0; i<len; ++i){
tot[i]=(long long)(A[i].real+0.5);
}
for(int i=0; i<n; ++i){
--tot[a[i]+a[i]];
}
for(int i=0; i<len; ++i){
tot[i]>>=1;
}
for(int i=1; i<len; ++i){
tot[i]+=tot[i-1];
}
sort(a,a+n);
long long res=0;
for(int i=0; i<n; ++i){
long long tmp=tot[len-1]-tot[a[i]];
tmp-=n-1; // 本身与其它的组合
tmp-=(long long)i*(n-i-1); // 小于与大于等于的组合
if(n-i-1>1) tmp-=(long long)(n-i-1)*(n-i-2)/2; // 大于等于之间的组合
res+=tmp;
}
printf("%.7f\n",res*1.0/((long long)n*(n-1)*(n-2)/6));
}
return 0;
}

HDU4609 3-idiots(母函数 + FFT)的更多相关文章

  1. 3-idiots hdu4609 母函数+FFT 组合数学题

    http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:1e5个数,求取三个数能形成三角形的概率. 题解(这怎么会是fft入门题QAQ): 概率的算法就是三 ...

  2. UVa12298 Super Poker II(母函数 + FFT)

    题目 Source http://acm.hust.edu.cn/vjudge/problem/23590 Description I have a set of super poker cards, ...

  3. SPOJ - TSUM 母函数+FFT+容斥

    题意:n个数,任取三个加起来,问每个可能的结果的方案数. 题解:构造母函数ABC,比如现在有 1 2 3 三个数.则 其中B表示同一个数加两次,C表示用三次.然后考虑去重. A^3表示可重复地拿三个. ...

  4. BZOJ.3771.Triple(母函数 FFT 容斥)

    题目链接 \(Description\) 有\(n\)个物品(斧头),每个物品价值不同且只有一件,问取出一件.两件.三件物品,所有可能得到的价值和及其方案数.\((a,b),(b,a)\)算作一种方案 ...

  5. SPOJ:Triple Sums(母函数+FFT)

    You're given a sequence s of N distinct integers.Consider all the possible sums of three integers fr ...

  6. 2019.01.02 bzoj3513: [MUTC2013]idiots(fft)

    传送门 fftfftfft经典题. 题意简述:给定nnn个长度分别为aia_iai​的木棒,问随机选择3个木棒能够拼成三角形的概率. 思路:考虑对于木棒构造出生成函数然后可以fftfftfft出两个木 ...

  7. [hdu4609]计数方法,FFT

    题目:给一个数组a,从里面任选三个数,求以这三个数为三条边能构成三角形的概率. 思路:由于每个数只能用一次,所以考虑枚举三边中的最大边.先将a数组排序,然后枚举它的每个数x作为最大边,那么问题就是要求 ...

  8. [HDU4609] 3-idiots - 多项式乘法,FFT

    题意:有\(n\)个正整数,求随机选取一个3组合,能构成三角形的概率. Solution: 很容易想到构造权值序列,对其卷积得到任取两条边(可重复)总长度为某数时的方案数序列,我们希望将它转化为两条边 ...

  9. 【自用】OI计划安排表一轮

    网络流√ 上下界最大流√ 线性规划转费用流√ RMQ优化建图√ 单纯形√ 字符串相关 hash√ 扩展KMP 回文自己主动机 数据结构 平衡树 启示式合并 替罪羊树 LCT 树套树 KD-Tree 二 ...

随机推荐

  1. mongodb 3.2 用户权限管理配置

    使用mongodb 有段时间了,由于是在内网使用,便没有设置权限,一直是裸奔. 最近有时间,研究了下mongodb 3.2 的用户权限配置,网上有许多用户权限配置的文章,不过大多是之前版本,有些出入, ...

  2. 项目之solr全文搜索工具之创建项目索引库

    以创建项目baotao core为例 1.  在example目录下创建baotao-solr文件夹: 2.  将./solr下的solr.xml拷贝到baotao-solr目录下: 3.  在bao ...

  3. android的JNI 、 NDK 学习!

    转载的! Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) ...

  4. elipse插件整理

    整理一下用过的eclipse插件: 1. WindowBuilder :swing插件,可以拖啊拖啊拖出来一个窗口,可以显著提高开发效率.   官网: http://www.eclipse.org/w ...

  5. IE6中使用通用选择器模拟子选择器效果

    IE6及更低版本不支持高级选择器:IE7有个bug,对于子选择器和相邻同胞选择器,如果父元素和子元素有HTML注释,会出问题. 下面我们使用通用选择器来模拟子选择器的效果. 原理:首先在所有后代上应用 ...

  6. 跳出IFrame几种方式

    1. <script type="text/javascript"> if (top.location !== self.location) { top.locatio ...

  7. [LeetCode] TwoSum

    Given an array of integers, find two numbers such that they add up to a specific target number. The ...

  8. cordova+angularJS+ionic

    1.创建项目 2.路由 angular.module("starter",['ionic']) // 依赖 ionic 提供的ui-router .config(function ...

  9. [Qcon] 百姓网开发总结

    拿到的PPT看了之后,发现给出的很简洁,但每个步骤用处却非常有用,我们一个个来分析: 1. 集中开发环境,这些方法看似简单,但是都是很实用的方法,在我开发中看的出来,SVN无分支就能解决我现有部门的部 ...

  10. long和int的区别

    转自:http://blog.sina.com.cn/s/blog_6f62c9510101svjz.html 突然间就想到了long和int到底什么区别(发现有很多问题都是突然间想到的),然后百度. ...