【题意】给定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. vi之跳到指定行

    vi里怎样跳转到某一指定行 输入 :行号 :$跳到最后一行 gg跳到第一行.

  2. NYOJ-36 最长公共子序列 AC 分类: NYOJ 2014-01-03 20:54 155人阅读 评论(0) 收藏

    #include<stdio.h> #include<string.h> #define N 1010 #define max(x,y) x>y?x:y int dp() ...

  3. 一个简单的PHP登录演示(SESSION版 与 COOKIE版)

    //==============COOKIE版本的简单登录================ if ($_GET[out]){ setcookie('id',''); setcookie('pw','' ...

  4. Caffe训练好的网络对图像分类

    对于训练好的Caffe 网络 输入:彩色or灰度图片 做minist 下手写识别分类,不能直接使用,需去除均值图像,同时将输入图像像素归一化到0-1直接即可. #include <caffe/c ...

  5. Eclipse下如何导入jar包

    原地址:http://blog.csdn.net/justinavril/article/details/2783182 我们在用Eclipse开发程序的时候,经常想要用到第三方的jar包.这时候我们 ...

  6. yum源万能

    sed -i ‘s|^#baseurl|baseurl| ; s|^mirrorlist|#mirrorlist|’ /etc/yum.repos.d/*

  7. 【redis】02string类型和hash类型

    Redis的数据类型   Redis主要分为五个数据类型,一个是string,最简单的一个数据类型,hash,list, 还有set集合,还有zset有序集合,这是咱们redis的五种基础类型, 接下 ...

  8. 1009-2的N次方

    描述 编程精确计算2的N次方.(N是介于100和1000之间的整数). 输入 正整数N (100≤N≤1000) 输出 2的N次方 样例输入 200 样例输出 16069380442589902755 ...

  9. Ubuntu环境下利用ant编译nutch2.2.1 & 配置nutch2.2.1

    /×××××××××××××××××××××××××××××××××××××××××/ Author:xxx0624 HomePage:http://www.cnblogs.com/xxx0624/ ...

  10. 01 - 编译链接第一个wxWidgets3.0例子

    1. preprocessor #define __WXMSW__#define WXUSINGDLL 2. vc10中设置Include dir, lib dir, dll path VC++平台编 ...