HDU 4609 3-idiots (FFT-快速傅立叶变换)
【题意】给定N个树枝,求从中取出三个可以围成三角形的概率
【思路】
2013多校训练第一场比赛1010题。
一开始就想到了O(n^2)枚举前两个树枝和的算法,赛后群里大牛说计算所有两个树枝和的情况可以用FFT在O(NlogN)时间内做到,于是剩下的问题就便简单了,于是就滚去学FFT了~
FFT可以在O(NlogN)时间内计算点值将多项式A = a1•x1 + a2•x2 + …… + an•xn, B = b1•x1 + b2•x2 + …… + bn•xn由系数表示法( 系数向量a = (a1, a2, ……, an) )转换成点值表示法从而可以在O(N)时间内计算出多项式乘积然后再在O(NlogN)时间内把乘积的点值表示法转换成系数表示法(这一过程叫插值),达到加速多项式乘法的作用。
那么我们怎么通过多项式乘法来快速计算出两个数组任意一项和的结果呢?应该想到乘法和加法间的联系:指数。所以我们可以令数组中的项为多项式的系数,比如(1, 3, 3, 4)就可以表示成P = 1*x1+2*x3+1*x4,这样两个多项式的乘积对应指数的系数就表示两个多项式指数和为该数的方案数。
在此题中我们令num[i]表示树枝长度为i的树枝个数,我们把它当作多项式的系数向量,对自身做一次乘法,结果的系数向量就对应和为某个长度的个数。
举个例子,num = {0 1 0 2 1}, 则num * num = {0 0 1 0 4 2 4 4 1},
这个结果的意义如下:
从{1 3 3 4}取一个数,从{1 3 3 4}再取一个数
取两个数和为 2 的取法是一种:1+1
和为 4 的取法有四种:1+3, 1+3 ,3+1 ,3+1
和为 5 的取法有两种:1+4 ,4+1;
和为 6的取法有四种:3+3,3+3,3+3,3+3,3+3
和为 7 的取法有四种: 3+4,3+4,4+3,4+3
和为 8 的取法有 一种:4+4
当然这样的结果是任意两个数相加,而题目中要求本身不能重复使用,所以要把取同一个的组合的情况删掉:for (int i = 0; i < n; i ++) num[a[i]+a[i]] --;
然后我们统计方案采用无序的组合方法(即1\2\3和3\2\1等价),并假定x1<x2<x3,所以在总方案中要减一半:for (int i = 1; i < maxn; i ++) num[i] /= 2;
最后对数组求前缀和就求出了所有x+y<=z的情况:for (int i = 1; i < maxn; i ++) sum[i] = sum[i-1] + num[i];
枚举第三个树枝的长度把结果加起来计算概率,用1减后就是最后的结果了。
重要:这里为什么要先求x+y<=z而不直接求x+y>z呢?因为前面说了我们计算过程中是按照组合统计的,并且假定第三个树枝数最大,那么统计x+y>z的方案就比较麻烦,因为需要去除掉z<x\y的情况,但是统计x+y<=z就简单了~因为这样z必定大于x\y。
【代码】
这道题内存和时间卡的紧,FFT要用迭代的算法,递归算法会超内存。
- #include
- #include
- #include
- #include
- #include
- #include
- #define MID(x,y) ((x+y)/2)
- #define mem(a,b) memset(a,b,sizeof(a))
- using namespace std;
const double eps = 1e-8;
const double Pi = acos(-1.0);
struct complex{
double r,i;
complex(double _r = 0,double _i = 0){
r = _r; i = _i;
}
complex operator +(const complex &b){
return complex(r+b.r,i+b.i);
}
complex operator -(const complex &b){
return complex(r-b.r,i-b.i);
}
complex operator *(const complex &b){
return complex(r*b.r-i*b.i,r*b.i+i*b.r);
}
};
struct FastFourierTransform{
inline int dcmp(double a){ if (aeps); }
void ReverseBits(complex *y, int len){
int i,j,k;
for(i = 1, j = len>>1; i > 1;
while(j >= k){
j -= k;
k >>= 1;
}
if(j nb) ? na : nb;
nc = 1;
while(nc 0 && dcmp(c[nc-1]) == 0; nc--);
// 这句加上时间还多了,不知道算不算优化……
delete ya; delete yb; delete yc;
}
//Convolution: r(k) = sigma(a[i]*b[i-k]){i=0~n-1}
//N must be power of 2
void Convolution(int *a, int *b, int *r, int n){
complex *d1 = new complex[n], *d2 = new complex[n], *y = new complex[n];
d1[0] = b[0];
int nc = 1;
while(nc
HDU 4609 3-idiots (FFT-快速傅立叶变换)的更多相关文章
Calculate A * B. Input Each line will contain two integers A and B. Process to end of file. Note: th ...
实数DFT,复数DFT,FFTFFT是计算DFT的快速算法,但是它是基于复数的,所以计算实数DFT的时候需要将其转换为复数的格式,下图展示了实数DFT和虚数DFT的情况,实数DFT将时域中N点信号转换 ...
题意:求两个数相乘. 第一次写非递归的fft,因为一个数组开小了调了两天TAT. #include<iostream> #include<cstring> #include&l ...
//最近突然发现博客园支持\(\rm\LaTeX\),非常高兴啊! 话说离省选只有不到五天了还在学新东西确实有点逗…… 切到正题,FFT还是非常神奇的一个东西,能够反直觉地把两个多项式相乘的时间复杂度 ...
您好,此教程将教大家使用scipy.fft分析wav文件的波频图.Time Domain.Frequency Domain. 实际案例:声音降噪,去除高频. 结果: 波频图: Time Domain:
自从去年下半年接触三维重构以来,听得最多的词就是傅立叶变换,后来了解到这个变换在图像处理里面也是重点中的重点. 本身自己基于高数知识的理解是傅立叶变换是将一个函数变为一堆正余弦函数的和的变换.而图像处 ...
已知多项式f(x)=a0+a1x+a2x2+...+am-1xm-1, g(x)=b0+b1x+b2x2+...+bn-1xn-1.利用卷积的蛮力算法,得到h(x)=f(x)g(x),这一过程的时间复 ...
\(2019.2.18upd:\) \(LINK\) 之前写的比较适合未接触FFT的人阅读--但是有几个地方出了错,大家可以找一下233 啊-本来觉得这是个比较良心的算法没想到这么抽搐这个算法真是将一 ...
BZOJ 2194 快速傅立叶变换之二 题意 给出两个长为\(n\)的数组\(a\)和\(b\),\(c_k = \sum_{i = k}^{n - 1} a[i] * b[i - k]\). 题解 ...
多项式 系数表示法 设\(f(x)\)为一个\(n-1\)次多项式,则 \(f(x)=\sum\limits_{i=0}^{n-1}a_i*x_i\) 其中\(a_i\)为\(f(x)\)的系数,用这 ...
随机推荐
如果是添加项目, 或修改了解决方案的配置, 会弹出这个是正常的. 如果在没有修改的情况下还这样就是有问题的. 原因: 在Vs中安装了PowerDesigner插件, 并在VS中点了该插件的东西 ...
Memcache安全配置 瞌睡龙 · 2014/01/20 17:59 0x00 Memcache简介 Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash ...
又是不带修改的区间第k大,这次用的是一个不同的方法,划分树,划分树感觉上是模拟了快速排序的过程,依照pivot不断地往下划分,然后每一层多存一个toleft[i]数组,就可以知道在这一层里从0到i里有 ...
对于linux的应用,我想大多数都是用在服务器领域,对于服务器来讲真的没有必要跑一个图形界面.所以我们平时安装linux操作系统时往往是不安装图形界面的.说到这里也许你会有疑问,图形界面还能选择装或者 ...
sudo vim /etc/network/interfaces, 将该文件的内容修改为如下:(也就是说删掉其他的什么auto eth0.auto wlan0) auto lo iface lo in ...
1.新建继承ContentProvider的类 package com.wangzhu.demo; import android.content.ContentProvider; import and ...
1.matlab中的imread相当于OpenCV中的cvLoadImage(imageName, CV_LOAD_IAMGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR): ...
6.1 模板的概念 C++允许用同一个函数定义函数,这些函数的参数个数和参数类型不同.例如求最大值的max函数, int max(int x,int y) { return (x>y ...
原文地址:http://www.cnblogs.com/liaoyu/p/uushop.html 源码地址:https://github.com/liaoyu/uushop 贴出一个大学时做的小项目, ...
基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现. @Component:对类进行标注,Spring容器 ...