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 二 ...
随机推荐
- MongoDB 基础 -安全性-(权限操作)
和其他所有数据库一样,权限的管理都差不多一样.mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名.密码和数据库信息.mongodb默认不启用授权认证,只要 ...
- Mysql 调用存储过程的两种方式
一,使用call语句: 如:创建 call 调用: 使用占位符,通过prepare,execute调用:
- Android 在 manifest 文件里增加 versionCode,运行后版本并没有随之增加
现象:从 git 上拉下来的代码中 versionCode 是8,versionName 是1.0.7但运行后的版本仍然是1.0.6 原因:全文搜索1.0.6之后发现在 bin 目录下也有一个 man ...
- backtracking(回溯算法)
http://blog.csdn.net/zxasqwedc/article/details/42270215 permutation的程式码都会长成这样的格式: ] = { 'a', 'b', 'c ...
- Swift - as、as!、as?三种类型转换操作使用一览
as.as!.as? 这三种类型转换操作符的异同,以及各自的使用场景. 1,as使用场合 (1)从派生类转换为基类,向上转型(upcasts) 1 2 3 4 class Animal {} cl ...
- JAVA基础学习之XMLCDATA区、XML处理指令、XML约束概述、JavaBean、XML解析(8)
1.CDATA区在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当作原始内容处理.遇到此种情况,可以把这些内容放在CDATA区里,对于CDATA区域内的内容,XML解析程序不会处理,而是直 ...
- Myeclipse 2016 & 2014 下载
myeclipse-2016-ci-6-offline-installer-windowshttps://downloads.genuitec.com/downloads/myeclipse/inst ...
- Pyqt QDockWidget 停靠窗体
网上的一个关于QDockWidget 停靠窗体的教程 代码: # -*- coding: utf-8 -*- from PyQt4.QtGui import * from PyQt4.QtCore i ...
- JavaScript高级程序设计 读书笔记
第一章 JavaScript 简介 第二章 Html中使用JavaScript 第三章 基本概念 第四章 变量,作用域,内存 第五章 引用类型 第六章 面向对象 第七章 函数表达式 第八章 BOM 第 ...
- APUE包含头文件"apue.h"问题
下载源码 从unix高级编程书籍官网下载书籍的上的所有源码. wget http://www.apuebook.com/src.tar.gz 解压这个文件 tar -zxvf src.tar.gz 解 ...