【题意】给定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-快速傅立叶变换)的更多相关文章

  1. FFT(快速傅立叶变换):HDU 1402 A * B Problem Plus

    Calculate A * B. Input Each line will contain two integers A and B. Process to end of file. Note: th ...

  2. FFT快速傅立叶变换的工作原理

    实数DFT,复数DFT,FFTFFT是计算DFT的快速算法,但是它是基于复数的,所以计算实数DFT的时候需要将其转换为复数的格式,下图展示了实数DFT和虚数DFT的情况,实数DFT将时域中N点信号转换 ...

  3. spoj VFMUL FFT快速傅立叶变换模板题

    题意:求两个数相乘. 第一次写非递归的fft,因为一个数组开小了调了两天TAT. #include<iostream> #include<cstring> #include&l ...

  4. FFT快速傅立叶变换

    //最近突然发现博客园支持\(\rm\LaTeX\),非常高兴啊! 话说离省选只有不到五天了还在学新东西确实有点逗…… 切到正题,FFT还是非常神奇的一个东西,能够反直觉地把两个多项式相乘的时间复杂度 ...

  5. FFT快速傅立叶变换:解析wav波频图、Time Domain、Frequency Domain

    您好,此教程将教大家使用scipy.fft分析wav文件的波频图.Time Domain.Frequency Domain. 实际案例:声音降噪,去除高频. 结果: 波频图: Time Domain:

  6. 离散傅立叶变换与快速傅立叶变换(DFT与FFT)

    自从去年下半年接触三维重构以来,听得最多的词就是傅立叶变换,后来了解到这个变换在图像处理里面也是重点中的重点. 本身自己基于高数知识的理解是傅立叶变换是将一个函数变为一堆正余弦函数的和的变换.而图像处 ...

  7. 快速傅立叶变换(FFT)算法

    已知多项式f(x)=a0+a1x+a2x2+...+am-1xm-1, g(x)=b0+b1x+b2x2+...+bn-1xn-1.利用卷积的蛮力算法,得到h(x)=f(x)g(x),这一过程的时间复 ...

  8. $\mathcal{FFT}$·$\mathcal{Fast \ \ Fourier \ \ Transformation}$快速傅立叶变换

    \(2019.2.18upd:\) \(LINK\) 之前写的比较适合未接触FFT的人阅读--但是有几个地方出了错,大家可以找一下233 啊-本来觉得这是个比较良心的算法没想到这么抽搐这个算法真是将一 ...

  9. BZOJ 2194 快速傅立叶变换之二 | FFT

    BZOJ 2194 快速傅立叶变换之二 题意 给出两个长为\(n\)的数组\(a\)和\(b\),\(c_k = \sum_{i = k}^{n - 1} a[i] * b[i - k]\). 题解 ...

  10. 快速傅立叶变换(FFT)

    多项式 系数表示法 设\(f(x)\)为一个\(n-1\)次多项式,则 \(f(x)=\sum\limits_{i=0}^{n-1}a_i*x_i\) 其中\(a_i\)为\(f(x)\)的系数,用这 ...

随机推荐

  1. 【BZOJ】【2253】【WC 2010 BeijingWC】纸箱堆叠

    树套树 Orz zyf 我的树套树不知道为啥一直WA……只好copy了zyf的写法TAT 这题还可以用CDQ分治来做……但是蒟蒻不会…… //y坐标的树状数组是按权值建的……所以需要离散化…… /** ...

  2. 【BZOJ】【1076】【SCOI2008】奖励关

    状压DP+数学期望 蒟蒻不会啊……看题跑…… Orz了一下Hzwer,发现自己现在真是太水了,难道不看题解就一道题也不会捉了吗? 题目数据范围不大……100*(2^16)很容易就跑过去了…… DP的时 ...

  3. 高性能网络编程2----TCP消息的发送

    转 陶辉 taohui.org.cn 在上一篇中,我们已经建立好的TCP连接,对应着操作系统分配的1个套接字.操作TCP协议发送数据时,面对的是数据流.通常调用诸如send或者write方法来发送数据 ...

  4. prefix springmvc

    设置了@RequestMapping("/jsp/info.do"),也可以写成"jsp/info.act"不影响 retuen "index&quo ...

  5. Lua print on the same line

    In Pascal, I have write and writeln. Apparently Lua's print is similar to writeln of Pascal. Do we h ...

  6. POJ2752 Seek the Name,Seek the Fame KMP算法

    KMP继续练手.题目问的是一个串前缀等于后缀的可能长度是哪些,输出来.题目考的是对KMP失配指针的理解,当最后一位失配(即'\0'那里)时,指针会移动到前缀对应匹配的部分,所以这个长度是我们要的,然后 ...

  7. 阻止事件冒泡(stopPropagation和cancelBubble)和阻止默认行为(preventDefault和returnValue)

    <div id="divId1" style="width:500px;height:500px;background-color:#3ac;text-align: ...

  8. Project Euler 95:Amicable chains 亲和数链

    Amicable chains The proper divisors of a number are all the divisors excluding the number itself. Fo ...

  9. MySQL 建表字段长度的限制

    脑补,varchar(N),N指的是最大字符数,不是字节数. 先上测试说明:   在MySQL建表时,遇到一个奇怪的现象: root@localhost : test 10:30:54>CREA ...

  10. Android:单元测试

    通过单元测试的方法可以轻松判断BUG 第一步:首先在AndroidManifest.xml中加入下面红色代码: 打开AndroidManifest.xml,选择instrumentation ,选择N ...