HDU4609 3-idiots(母函数 + FFT)
题目
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)的更多相关文章
- 3-idiots hdu4609 母函数+FFT 组合数学题
http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:1e5个数,求取三个数能形成三角形的概率. 题解(这怎么会是fft入门题QAQ): 概率的算法就是三 ...
- UVa12298 Super Poker II(母函数 + FFT)
题目 Source http://acm.hust.edu.cn/vjudge/problem/23590 Description I have a set of super poker cards, ...
- SPOJ - TSUM 母函数+FFT+容斥
题意:n个数,任取三个加起来,问每个可能的结果的方案数. 题解:构造母函数ABC,比如现在有 1 2 3 三个数.则 其中B表示同一个数加两次,C表示用三次.然后考虑去重. A^3表示可重复地拿三个. ...
- BZOJ.3771.Triple(母函数 FFT 容斥)
题目链接 \(Description\) 有\(n\)个物品(斧头),每个物品价值不同且只有一件,问取出一件.两件.三件物品,所有可能得到的价值和及其方案数.\((a,b),(b,a)\)算作一种方案 ...
- SPOJ:Triple Sums(母函数+FFT)
You're given a sequence s of N distinct integers.Consider all the possible sums of three integers fr ...
- 2019.01.02 bzoj3513: [MUTC2013]idiots(fft)
传送门 fftfftfft经典题. 题意简述:给定nnn个长度分别为aia_iai的木棒,问随机选择3个木棒能够拼成三角形的概率. 思路:考虑对于木棒构造出生成函数然后可以fftfftfft出两个木 ...
- [hdu4609]计数方法,FFT
题目:给一个数组a,从里面任选三个数,求以这三个数为三条边能构成三角形的概率. 思路:由于每个数只能用一次,所以考虑枚举三边中的最大边.先将a数组排序,然后枚举它的每个数x作为最大边,那么问题就是要求 ...
- [HDU4609] 3-idiots - 多项式乘法,FFT
题意:有\(n\)个正整数,求随机选取一个3组合,能构成三角形的概率. Solution: 很容易想到构造权值序列,对其卷积得到任取两条边(可重复)总长度为某数时的方案数序列,我们希望将它转化为两条边 ...
- 【自用】OI计划安排表一轮
网络流√ 上下界最大流√ 线性规划转费用流√ RMQ优化建图√ 单纯形√ 字符串相关 hash√ 扩展KMP 回文自己主动机 数据结构 平衡树 启示式合并 替罪羊树 LCT 树套树 KD-Tree 二 ...
随机推荐
- August 14th, Week 34th Sunday, 2016
To live is to function, that is all there is in living. 活着就要发挥作用,这就是生活的全部内容. I often joke that my dr ...
- ui组件--弹出层layer的使用
帮助文档 下载地址 演示地址
- grep如何忽略.svn目录,以及如何忽略多个目录
grep如何忽略.svn目录,以及如何忽略多个目录 这是我在网上看到的文章,不过里面还有问题,我的不支持,需要更换架包 grep -r 'function_name' * (*表示当前目录下所有文件, ...
- nyoj998(euler)
题意:题意:给出n和m,求满足条件gcd(x, n)>=m的x的gcd(x, n)的和,其中1<=x<=n,1<= n, m <= 1e9:思路:此题和nyoj1007差 ...
- 直接放个DB2 SQL STATEMENT大全好了!
SQL statements This topic contains tables that list the SQL statements classified by type. SQL sch ...
- NYOJ题目816它合法吗?
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtIAAAJ0CAIAAACwTVMOAAAgAElEQVR4nO3du1LjzNo24O8kyDkQYh
- PHP面向对象——异常处理
Error_reporting(0); //在网站正式上线的时候不准他报任何错误. 错误级别为不允许报错 Exception 是所有异常的基类. 测试并捕捉一个错误的例子: class mysq ...
- IOS 开发,调用打电话,发短信,打开网址
IOS 开发,调用打电话,发短信,打开网址 1.调用 自带mail [[UIApplication sharedApplication] openURL:[NSURL URLWithString: ...
- 关于android的单位dp与px
原文:Android中dp和px之间进行转换 官方文档:http://developer.android.com/guide/practices/screens_support.html The de ...
- SQL跨项目查询语法
EXEC sp_addlinkedserver 'ITSV', '', 'SQLOLEDB', '192.168.1.248' EXEC sp_addlinkedsrvlogin 'ITSV', 'f ...