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

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

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

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

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

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

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

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

  1. #include <iostream>
  2. #include <cmath>
  3. #include <algorithm> //spell!
  4. #include <string.h>
  5. #define MAXN 400040
  6. #define PI acos(-1.0)
  7. using namespace std;
  8.  
  9. struct complex
  10. {
  11. double r,i;
  12. complex(double real=0.0,double image=0.0)
  13. {
  14. r=real;
  15. i=image;
  16. }
  17. //以下为三种虚数运算的定义
  18. complex operator+(const complex o)
  19. {
  20. return complex(r+o.r,i+o.i);
  21. }
  22. complex operator-(const complex o)
  23. {
  24. return complex(r-o.r,i-o.i);
  25. }
  26. complex operator*(const complex o)
  27. {
  28. return complex(r*o.r-i*o.i,r*o.i+i*o.r);
  29. }
  30. }x1[MAXN];
  31.  
  32. void bitrev(complex *y,int l) //二进制平摊反转置换 O(logn)
  33. {
  34. register int i,j,k;
  35. for(i=,j=l/;i<l-;i++)
  36. {
  37. if(i<j) swap(y[i],y[j]); //交换互为下标反转的元素
  38. //i<j保证只交换一次
  39. k=l/;
  40. while(j>=k) //由最高位检索,遇1变0,遇0变1,跳出
  41. {
  42. j-=k;
  43. k/=;
  44. }
  45. if(j<k) j+=k;
  46. }
  47. }
  48. void fft(complex *in,int n,int flag)
  49. {
  50. int i,j,k;
  51. complex u,t;
  52. bitrev(in,n);
  53. for(int i=;i<=n;i=i*)
  54. {
  55. complex wn(cos((*PI*flag)/i),sin((*PI*flag)/i));//初始化单位复根
  56. for(j=;j<n;j=j+i)
  57. {
  58. complex w(,);
  59. for(k=j;k<j+i/;k++)
  60. {
  61. u=in[k];
  62. t=w*in[k+i/];
  63. in[k]=u+t;
  64. in[k+i/]=u-t;
  65. w=w*wn;
  66. }
  67. }
  68. }
  69. if(flag==-)
  70. for(int i=;i<n;i++)
  71. in[i].r=in[i].r/n;
  72. }
  73.  
  74. int a[];
  75. long long res[MAXN];
  76. long long sum[MAXN];
  77. long long num[MAXN];
  78. int main() {
  79. int T;
  80. scanf("%d",&T);
  81. while(T--)
  82. {
  83. int n,i;
  84. scanf("%d",&n);
  85. memset(res,,sizeof(res));
  86. memset(sum,,sizeof(sum));
  87. memset(num,,sizeof(num));
  88. for(int j=;j<n;j++)
  89. {
  90. scanf("%d",&a[j]);
  91. num[a[j]]++;
  92. }
  93. sort(a,a+n);
  94. for(i = ;i <=a[n-];i++)
  95. {
  96. x1[i].r=num[i];
  97. x1[i].i=;
  98. }
  99. int expandn=;
  100. while(expandn<*(a[n-]+))expandn=expandn*;
  101.  
  102. for(i = a[n-]+;i<expandn;i++)
  103. {
  104. x1[i].r=;
  105. x1[i].i=;
  106. }
  107. fft(x1,expandn,);
  108. for(i=;i<expandn;i++)
  109. x1[i]=x1[i]*x1[i];
  110. fft(x1,expandn,-);
  111. for(i=;i<expandn;i++)
  112. {
  113. res[i]=(long long)(x1[i].r+0.5);
  114. }
  115. //去除本身
  116. for(i=;i<n;i++)
  117. res[a[i]+a[i]]--;
  118. //变为组合
  119. for(i=;i<expandn;i++)
  120. res[i]=res[i]/;
  121. //求出两边之和为i的所有可能
  122. //expandn=(a[n-1]+1)*2;
  123. sum[]=res[];
  124. for(i=;i<expandn;i++)
  125. sum[i]=res[i]+sum[i-];
  126. long long ans=;
  127. for(i=;i<n;i++)
  128. {
  129. ans+=sum[expandn-]-sum[a[i]];//比长度为a[i]大的所有可能
  130. //去除一个大于a[i],一个小于a[i]
  131. ans=ans-(long long)(n--i)*i;
  132. //去除一个取自己
  133. ans=ans-(n-);
  134. //去除取两个都大
  135. ans=ans-(long long)(n--i)*(n--i)/;
  136. }
  137. long long all = (long long)n*(n-)*(n-)/;
  138. printf("%.7lf\n",(double)ans/all);
  139. }
  140. }

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. mac 下 安装 mongodb 数据库

    1.在网上下载mongodb 安装包,官方网站 mongodb.org/downloads 2.将下载的安装文件放在指定目录下,例 User/电脑名/文件夹名... 3.解压安装包,如需改名,新建文件 ...

  2. Jmeter接口測试

    一.创建project.引包 1.创建JAVAproject 2.引入Jmeter中lib\ext基础包:ApacheJMeter_java.jar.ApacheJMeter_core.jar 3.引 ...

  3. AndroidStudio 0.2.x 引入多模块Eclipse项目

    !!!!太他妈的累人了!整整折腾了两天!!!!!!! 不知从那个版本开始ImportModule... 从AndroidStudio的File菜单中消失了,在0.2之前的版本作为library的模块可 ...

  4. EnumMap源代码阅读器

    EnumMap是一个用于存放键值为enum类型的map.全部的键值必须来自一个单一的enum类型.EnumMap内部用数组表示效率更高. EnumMap维持键值的自然顺序(即枚举类型常量声明的顺序), ...

  5. malloc、calloc、realloc三者的差别

    1.malloc 作用:分配内存块 原型:void *malloc(size_t size);size表示要分配的字节数 返回值:返回一个指向所分配空间的void指针,假设没有足够的内存可用,则返回N ...

  6. 使用autoCompleteTextView以及MultiAutoCompleteTextView实现自动匹配输入内容

    一:autoCompleteTextView 1:控件属性设置: 注意添加:android:completionThreshold="1"来设置输入几个字符的时候开始显示匹配的内容 ...

  7. 解决虚拟内存不够导致Eclipse is not responding

    安装目录下eclipse.ini中: 修改参数至必要大小. e.g. -vmargs-Djava.net.preferIPv4Stack=true-Dosgi.requiredJavaVersion= ...

  8. JS拖动DIV布局

    方法一: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  9. PHP学习笔记9-生成图片

    用PHP代码在网页上生成图片 <?php /** * Created by PhpStorm. * User: Administrator * Date: 2015/6/29 * Time: 2 ...

  10. Laravel 5.1 ACL权限控制 一

    请自行添加命名空间,代码下载地址 https://github.com/caoxt/learngit 1.所需要用到的数据表 users(用户表).roles(角色表).role_user(用户角色对 ...