3-idiots hdu4609 母函数+FFT 组合数学题
http://acm.hdu.edu.cn/showproblem.php?pid=4609
题意:1e5个数,求取三个数能形成三角形的概率。
题解(这怎么会是fft入门题QAQ):
概率的算法就是三角形取法/总取法。总取法就是C(n,3).
三角形取法如何计算?
part1:构造母函数F(日常套路),每一项的次数为长度,系数为该长度的木棍数量,用FFT算F^2 ,
得到的多项式就包含了任意取两跟棍子得到的所有长度的方案数:其中次数为两根棍长之和,系数为该长度的方案数,
part2:去重,考虑part1中得到的系数,并非方案数(举个例子,(a+b)^2==a^2+b^2+2ab)
首先,对于每个平方项,因为棍子不能重复使用,所以对于k^m要减去平方前k^(m/2)的系数,
其次,对于剩下的每一项,由于多项式乘法每个乘法都做了两遍,所以得到的系数为方案数的两倍。要/2.
我们将处理过的系数存入数组A。
part3:算方案数:为了避免重复,对于每一根的木棍,计算以它为最长边的三角形方案数:为该长度到最大长度的A的系数和,(前缀和O(1)算出)
减去其中包含它的方案数,为1*(n-1).
减去其中它不是最长的方案数,为(n-1-1)*比它长的木棍数-两根都比它长的方案数/2(乘法原理多算了一遍,容斥减去),也可以理解为 一根比它长一根比他短+两根都比他长/2.(其中比它长的木棍数并不需要树状数组,只要排个序,他就是n-i)
end
总之,fft只是一个开始,后面巨麻烦orz
坑:套miskcoo dalao的fft,结果发现别人的是魔改版的,需要深刻地理解fft才会用orz
ac代码:
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
#include<complex>
using namespace std;
//const double eps(1e-8);
typedef long long lint; const double PI = acos(-1.0); const int MaxL = , MaxN = << MaxL;
typedef complex<double> complex_t;
complex_t f[MaxN], g[MaxN];
complex_t eps[MaxN], inv_eps[MaxN];
void init_eps(int p)
{
double pi = acos(-);
//double angle = 2.0 * pi / p;
for (int i = ; i != p; ++i)
eps[i] = complex_t(cos(2.0 * pi * i / p), sin(2.0 * pi * i / p));
for (int i = ; i != p; ++i)
inv_eps[i] = conj(eps[i]);
} void transform(int n, complex_t *x, complex_t *w)
{
for (int i = , j = ; i != n; ++i)
{
if (i > j) std::swap(x[i], x[j]);
for (int l = n >> ; (j ^= l) < l; l >>= );
} for (int i = ; i <= n; i <<= )
{
int m = i >> ;
for (int j = ; j < n; j += i)
{
for (int k = ; k != m; ++k)
{
complex_t z = x[j + m + k] * w[n / i * k];
x[j + m + k] = x[j + k] - z;
x[j + k] += z;
}
}
}
} int branch[];
int num[];
complex_t a[];//(1 << 17 = 131072, 1 << 18 = 262144)
lint A[];
lint sumA[];//表示A[i]的前缀和 int main()
{
int T, n;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
int maxBranch = ;
for (int i = ; i < n; i++)
{
scanf("%d", branch + i);
maxBranch = max(maxBranch, branch[i]);
}
memset(num, , sizeof(num));
for (int i = ; i < n; i++)
num[branch[i]]++;
for (int i = ; i <= maxBranch; i++)
a[i] = num[i];
int len = ;
while (len <= maxBranch) len <<= ;
len <<= ;
for (int i = maxBranch + ; i < len; i++)
a[i] = 0.0;
init_eps(len);
transform( len,a ,eps);
for (int i = ; i < len; i++)
a[i] = a[i] * a[i];
transform( len,a, inv_eps);
for (int i = ; i <= * maxBranch; i++)
A[i] = (lint)(a[i].real() + 0.5)/len;
for (int i = ; i <= * maxBranch; i += )
A[i] -= num[i >> ];
for (int i = ; i <= * maxBranch; i++)
A[i] /= ;
//到现在为止A[i]表示的是取两根不同的branch的长度和为i的组合种数
sumA[] = ;
for (int i = ; i <= * maxBranch; i++)
sumA[i] = sumA[i - ] + A[i];
lint ans = ;
sort(branch, branch + n);
for (int i = ; i <= n; i++)//以第i根作为边最长的
{
lint tmp = sumA[ * maxBranch] - sumA[branch[i]];//另外两条边长度和要大于branch[i]
tmp -= (lint)(n - i)*(n - );//比它长
tmp += (lint)(n - i)*(n - i - ) / ;//两条都比他长
tmp -= n - ;//另外两条的组合中包括它自己的组合
ans += tmp;
}
double p = ans * . / n / (n - ) / (n - );
printf("%.7f\n", p);
}
cin >> n;
return ;
}
/*
*/
/*
2
4
1 3 3 4
4
2 3 3 4 */
3-idiots hdu4609 母函数+FFT 组合数学题的更多相关文章
- HDU4609 FFT+组合计数
HDU4609 FFT+组合计数 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意: 找出n根木棍中取出三根木棍可以组成三角形的概率 题解: ...
- 组合数学题 Codeforces Round #108 (Div. 2) C. Pocket Book
题目传送门 /* 题意:每一次任选i,j行字符串进行任意长度前缀交换,然后不断重复这个过程,问在过程中,第一行字符串不同的个数 组合数学题:每一列不同的字母都有可能到第一行,所以每列的可能值相乘取模就 ...
- HDU4609 3-idiots(母函数 + FFT)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4609 Description King OMeGa catched three men wh ...
- BZOJ.3771.Triple(母函数 FFT 容斥)
题目链接 \(Description\) 有\(n\)个物品(斧头),每个物品价值不同且只有一件,问取出一件.两件.三件物品,所有可能得到的价值和及其方案数.\((a,b),(b,a)\)算作一种方案 ...
- UVa12298 Super Poker II(母函数 + FFT)
题目 Source http://acm.hust.edu.cn/vjudge/problem/23590 Description I have a set of super poker cards, ...
- BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]
4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...
- BZOJ 4555: [Tjoi2016&Heoi2016]求和 [FFT 组合计数 容斥原理]
4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...
- SPOJ - TSUM 母函数+FFT+容斥
题意:n个数,任取三个加起来,问每个可能的结果的方案数. 题解:构造母函数ABC,比如现在有 1 2 3 三个数.则 其中B表示同一个数加两次,C表示用三次.然后考虑去重. A^3表示可重复地拿三个. ...
- SPOJ:Triple Sums(母函数+FFT)
You're given a sequence s of N distinct integers.Consider all the possible sums of three integers fr ...
随机推荐
- 【Sqlserver】SqlServer中EXEC 与 SP_EXECUTESQL的 区别
MSSQL为我们提供了两种动态执行SQL语句的命令,分别是 EXEC 和 SP_EXECUTESQL ,我们先来看一下两种方式的用法. 先建立一个表,并添加一些数据来进行演示: CREATE TABL ...
- Atitit 手机图片备份解决方案attilax总结
Atitit 手机图片备份解决方案attilax总结 1.1. 图片分类 相机图片与app图片1 1.2. 增量备份,只能使用按照时间法备份..1 1.3. 备份工具选型1 1.4. App图片,只好 ...
- Atitit 快速开发体系建设路线图
Atitit 快速开发体系建设路线图 1.1. 项目类型划分 哑铃型 橄榄型 直板型(可以立即实行)1 1.2. 解决方案知识库 最佳实践库 最佳流程优化(已成,需要一些整理)2 1.3. 功能模板 ...
- Verilog TestBench Coding Style
Abtract 关于编写testbench的一些经验总结心得. Introduction 1.基本的Testbench结构 1)常用的编码结构 `timescale 1 ns / 1 ps ...
- ffmpeg主体架构分析
[时间:2016-07] [状态:Open] [关键词:ffmpeg,libavcodec,libavformat] FFmpeg接触几年了,用的比较多的是libavcodec和libavformat ...
- java框架篇---hibernate之CRUD操作
CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写. 下面列举实例来讲解这几个操作: 实体类: ...
- layui.laytpl中js方法书写及调用:去除html标签
<script type="text/html" id="conTpl"> {{# var delhtml = function(str) { ...
- android中通过intent传递复杂数据
android中在各个service或者acitivity之间可以通过Intent来传递一些数据,intent原生直接提供了一些简单数据类型的数据的传递,使用起来也很方便,比如int boolean ...
- git技巧
工作区 -> git add -> 暂存区 -> git commit -> 版本库 -> git push -> 远程仓库 版本库HEAD表示当前版本,上一个版本 ...
- 嵌入式开发之hi3519---PCIE DMA
http://blog.csdn.net/abcamus/article/details/76167747 大话pcie dma http://blog.csdn.net/qingfengtsing/ ...