快速傅里叶变化有不同的应用场景,hdu4609就比较有意思。题目要求是给n个线段,随机从中选取三个,组成三角形的概率。

初始实在没发现这个怎么和FFT联系起来,后来看了下别人的题解才突然想起来:组合计数问题可以用多项式的卷积来解决。于是将给的数据进行卷积相乘,利用FFT即可求出三角形任意两条线段组合的可能数目。

然后遍历初始数据,将其作为最长边(这里一开始也没想明白,其实就是只要最长边大于短边之和,其他两个不等式也自然可以满足)。那么理论上说比它长的所有两边组合可能都可以。当然在这里要考虑三种特殊情况:(即在两边组合数目中减去这些情况)

1.这两个边有可能一个边比最长边长,一个边小于最长边

2.其中一个边就是要选的这个边

3.两个边其实都比最长边长,这种情况要除以二

PS:G++使用的是longlong类型,C++是_int64,好久没写忘记了。

longlong在代码中间乘的运算也要加上,否则还是会出错。

#include <iostream>
#include <cmath>
#include <algorithm> //spell!
#include <string.h>
#define MAXN 400040
#define PI acos(-1.0)
using namespace std; struct complex
{
double r,i;
complex(double real=0.0,double image=0.0)
{
r=real;
i=image;
}
//以下为三种虚数运算的定义
complex operator+(const complex o)
{
return complex(r+o.r,i+o.i);
}
complex operator-(const complex o)
{
return complex(r-o.r,i-o.i);
}
complex operator*(const complex o)
{
return complex(r*o.r-i*o.i,r*o.i+i*o.r);
}
}x1[MAXN]; void bitrev(complex *y,int l) //二进制平摊反转置换 O(logn)
{
register int i,j,k;
for(i=,j=l/;i<l-;i++)
{
if(i<j) swap(y[i],y[j]); //交换互为下标反转的元素
//i<j保证只交换一次
k=l/;
while(j>=k) //由最高位检索,遇1变0,遇0变1,跳出
{
j-=k;
k/=;
}
if(j<k) j+=k;
}
}
void fft(complex *in,int n,int flag)
{
int i,j,k;
complex u,t;
bitrev(in,n);
for(int i=;i<=n;i=i*)
{
complex wn(cos((*PI*flag)/i),sin((*PI*flag)/i));//初始化单位复根
for(j=;j<n;j=j+i)
{
complex w(,);
for(k=j;k<j+i/;k++)
{
u=in[k];
t=w*in[k+i/];
in[k]=u+t;
in[k+i/]=u-t;
w=w*wn;
}
}
}
if(flag==-)
for(int i=;i<n;i++)
in[i].r=in[i].r/n;
} int a[];
long long res[MAXN];
long long sum[MAXN];
long long num[MAXN];
int main() {
int T;
scanf("%d",&T);
while(T--)
{
int n,i;
scanf("%d",&n);
memset(res,,sizeof(res));
memset(sum,,sizeof(sum));
memset(num,,sizeof(num));
for(int j=;j<n;j++)
{
scanf("%d",&a[j]);
num[a[j]]++;
}
sort(a,a+n);
for(i = ;i <=a[n-];i++)
{
x1[i].r=num[i];
x1[i].i=;
}
int expandn=;
while(expandn<*(a[n-]+))expandn=expandn*; for(i = a[n-]+;i<expandn;i++)
{
x1[i].r=;
x1[i].i=;
}
fft(x1,expandn,);
for(i=;i<expandn;i++)
x1[i]=x1[i]*x1[i];
fft(x1,expandn,-);
for(i=;i<expandn;i++)
{
res[i]=(long long)(x1[i].r+0.5);
}
//去除本身
for(i=;i<n;i++)
res[a[i]+a[i]]--;
//变为组合
for(i=;i<expandn;i++)
res[i]=res[i]/;
//求出两边之和为i的所有可能
//expandn=(a[n-1]+1)*2;
sum[]=res[];
for(i=;i<expandn;i++)
sum[i]=res[i]+sum[i-];
long long ans=;
for(i=;i<n;i++)
{
ans+=sum[expandn-]-sum[a[i]];//比长度为a[i]大的所有可能
//去除一个大于a[i],一个小于a[i]
ans=ans-(long long)(n--i)*i;
//去除一个取自己
ans=ans-(n-);
//去除取两个都大
ans=ans-(long long)(n--i)*(n--i)/;
}
long long all = (long long)n*(n-)*(n-)/;
printf("%.7lf\n",(double)ans/all);
}
}

hdu 4609

快速傅里叶变换应用之二 hdu 4609 3-idiots的更多相关文章

  1. 基于python的快速傅里叶变换FFT(二)

    基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点  FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...

  2. 解题:HDU 4609 Three Idiots

    题面 要求组合的方法显然我们需要对桶卷积,即设$F(x)=\sum\limits_{i=1}^{maxx}x^{cnt[i]}$,然后我们初步的先把$F^2(x)$卷出来,表示选两条边.然后我们发现如 ...

  3. HDU 1402 A * B Problem Plus 快速傅里叶变换 FFT 多项式

    http://acm.hdu.edu.cn/showproblem.php?pid=1402 快速傅里叶变换优化的高精度乘法. https://blog.csdn.net/ggn_2015/artic ...

  4. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  5. 「快速傅里叶变换(FFT)」学习笔记

    FFT即快速傅里叶变换,离散傅里叶变换及其逆变换的快速算法.在OI中用来优化多项式乘法. 本文主要目的是便于自己整理.复习 FFT的算法思路 已知两个多项式的系数表达式,要求其卷积的系数表达式. 先将 ...

  6. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  7. 快速傅里叶变换(FFT)

    扯 去北京学习的时候才系统的学习了一下卷积,当时整理了这个笔记的大部分.后来就一直放着忘了写完.直到今天都腊月二十八了,才想起来还有个FFT的笔记没整完呢.整理完这个我就假装今年的任务全都over了吧 ...

  8. 研究傅里叶变换的一本好书<<快速傅里叶变换及其C程序>>

    快速傅里叶变换及其C程序 <快速傅里叶变换及其C程序>是中国科学技术大学出版社出版的.本书系统地介绍了傅里叶变换的理论和技术,内容包括傅里叶变换(FT)的定义.存在条件及其性质,离散傅里叶 ...

  9. 快速傅里叶变换(FFT)学习笔记(未完待续)

    目录 参考资料 FFT 吹水 例题 普通做法 更高大尚的做法 定义与一部分性质 系数表达式 点值表达式 点值相乘??? 卷积 复数 单位根 DFT IDFT 蝴蝶迭代优化 单位根求法 实现.细节与小优 ...

随机推荐

  1. java实现字符串匹配问题之求两个字符串的最大公共子串

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/38924981 近期在项目工作中有一个关于文本对照的需求,经过这段时间的学习,总结 ...

  2. Oracle EBS Web ADI 中的术语

    Oracle EBS Web ADI 中的术语 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 异步调用异步调用是这样子的,和引入接口表中的数 ...

  3. ExtJs 4 的filefield上传后 返回值success接受不正常

    问题解决了,我修改了返回类型为setContentType("text/html")可以正确解析了,感到很奇怪,其他的地方使用setContentType("applic ...

  4. ping的意思

    Ping是测试网络联接状况以及信息包发送和接收状况非常有用的工具,是网络测试最常用的命令.Ping向目标主机(地址)发送一个回送请求数据包,要求目标主机收到请求后给予答复,从而判断网络的响应时间和本机 ...

  5. 「OC」类的深入研究、description方法和sel

    一.类的深入研究 (一)类的本质 类本身也是一个对象,是class类型的对象,简称“类对象”. Class类型的定义: Typedef struct obj class *class; 类名就代表着类 ...

  6. Eclipse安装反编译插件JD(Java Decompiler)

    JD安装说明:*****Eclipse 插件安装*****1. 在网上搜索并下载jdeclipse_update_site.zip2. Eclipse -> Install New Softwa ...

  7. oracle 集合变量以及自定义异常的用法

    oracle 集合变量以及自定义异常的用法, 在过程 record_practice 有record变量和自定义异常的用法实例.具体在3284行. CREATE OR REPLACE Package ...

  8. [LeetCode]题解(python):021-Merge Two Sorted Lists

    题目来源: https://leetcode.com/problems/merge-two-sorted-lists/ 题意分析: 题目给出两个排好序的链表,将这两个链表整合成一个新的有序的链表. 题 ...

  9. 用Xamarin 实现园友的 :Android浮动小球与开机自启动

    原文:用Xamarin 实现园友的 :Android浮动小球与开机自启动 前两天看园子里有筒子写了个 Android浮动小球与开机自启动  , 感觉这种被 360 玩烂的功能原来是如此的简单啊... ...

  10. Redhat 5.8系统安装R语言作Arima模型预测

    请见Github博客:http://wuxichen.github.io/Myblog/timeseries/2014/09/02/RJavaonLinux.html