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 二 ...
随机推荐
- jsdoc文档
官网文档:http://usejsdoc.org/index.html一个比较全的jsdoc示例 /** * @fileoverview 文件上传队列列表显示和处理 * @author 水车 **/ ...
- TortoiseSVN中Branching和Merging实践
转自:http://blog.csdn.net/eggcalm/article/details/6606520 使用svn几年了,一直对分支和合并敬而远之,一来是因为分支的管理不该我操心,二来即使涉及 ...
- Navicat 回复 psc 文件 Mysql
在mysql 中回复 psc文件 的时候 只能一步步来,先在navicat中建一个空数据库,然后点击有上角的备份==>回复备份==> 找到psc文件==> 注意此时不要急于点击 开始 ...
- iOS系类教程之用instruments来检验你的app
比较了好多关于instruments 还是发现老外写的比较牛逼.于是果断翻译过来.有能力的的可以去看英文原版,鼓励大家看原版资料远离二手教程.这里是原文 入门 为了节省大家的时间,提供一个演示的D ...
- jquery学习笔记---requirejs 和模块化编程
http://www.cnblogs.com/lisongy/p/4711056.html jquery模块化编程:http://www.cnblogs.com/digdeep/p/4602460.h ...
- .net学习笔记---webconfig的读与写
System.ConfigurationManager类用于对配置文件的读取.其具有的成员如下: 一.AppSettings AppSetting是最简单的配置节,读写非常简单. 名称 说明 AppS ...
- SVM NG课件1
SVM NG课件1 2014年9月28日 16:39 一个二维空间点的示例 已使用 Microsoft OneNote 2013 创建.
- ODATA WEB API(二)----ODATA服务与客户端
一.概述 ODATA不经可以作为WebAPI建立相应的WEBAPI控制器,还可以建立ODataControl控制器,能够通过插件建立第三方ODataClinet类库:调用和使用数据变得简单可行. 二. ...
- 浅析配置更快的Eclipse方法
很多人感觉自己的elipse启动比较慢,其实并不是因为装的插件太多或者是导入的项目有点大,而是因为参数的设置不合理导致的.可以在eclipse.ini里面添加-Xloggc:gc.log看看启动的日志 ...
- poj 1008:Maya Calendar(模拟题,玛雅日历转换)
Maya Calendar Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 64795 Accepted: 19978 D ...