快速傅里叶变换应用之二 hdu 4609 3-idiots
快速傅里叶变化有不同的应用场景,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的更多相关文章
- 基于python的快速傅里叶变换FFT(二)
基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点 FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...
- 解题:HDU 4609 Three Idiots
题面 要求组合的方法显然我们需要对桶卷积,即设$F(x)=\sum\limits_{i=1}^{maxx}x^{cnt[i]}$,然后我们初步的先把$F^2(x)$卷出来,表示选两条边.然后我们发现如 ...
- HDU 1402 A * B Problem Plus 快速傅里叶变换 FFT 多项式
http://acm.hdu.edu.cn/showproblem.php?pid=1402 快速傅里叶变换优化的高精度乘法. https://blog.csdn.net/ggn_2015/artic ...
- [学习笔记] 多项式与快速傅里叶变换(FFT)基础
引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...
- 「快速傅里叶变换(FFT)」学习笔记
FFT即快速傅里叶变换,离散傅里叶变换及其逆变换的快速算法.在OI中用来优化多项式乘法. 本文主要目的是便于自己整理.复习 FFT的算法思路 已知两个多项式的系数表达式,要求其卷积的系数表达式. 先将 ...
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...
- 快速傅里叶变换(FFT)
扯 去北京学习的时候才系统的学习了一下卷积,当时整理了这个笔记的大部分.后来就一直放着忘了写完.直到今天都腊月二十八了,才想起来还有个FFT的笔记没整完呢.整理完这个我就假装今年的任务全都over了吧 ...
- 研究傅里叶变换的一本好书<<快速傅里叶变换及其C程序>>
快速傅里叶变换及其C程序 <快速傅里叶变换及其C程序>是中国科学技术大学出版社出版的.本书系统地介绍了傅里叶变换的理论和技术,内容包括傅里叶变换(FT)的定义.存在条件及其性质,离散傅里叶 ...
- 快速傅里叶变换(FFT)学习笔记(未完待续)
目录 参考资料 FFT 吹水 例题 普通做法 更高大尚的做法 定义与一部分性质 系数表达式 点值表达式 点值相乘??? 卷积 复数 单位根 DFT IDFT 蝴蝶迭代优化 单位根求法 实现.细节与小优 ...
随机推荐
- mac 下 安装 mongodb 数据库
1.在网上下载mongodb 安装包,官方网站 mongodb.org/downloads 2.将下载的安装文件放在指定目录下,例 User/电脑名/文件夹名... 3.解压安装包,如需改名,新建文件 ...
- Jmeter接口測试
一.创建project.引包 1.创建JAVAproject 2.引入Jmeter中lib\ext基础包:ApacheJMeter_java.jar.ApacheJMeter_core.jar 3.引 ...
- AndroidStudio 0.2.x 引入多模块Eclipse项目
!!!!太他妈的累人了!整整折腾了两天!!!!!!! 不知从那个版本开始ImportModule... 从AndroidStudio的File菜单中消失了,在0.2之前的版本作为library的模块可 ...
- EnumMap源代码阅读器
EnumMap是一个用于存放键值为enum类型的map.全部的键值必须来自一个单一的enum类型.EnumMap内部用数组表示效率更高. EnumMap维持键值的自然顺序(即枚举类型常量声明的顺序), ...
- malloc、calloc、realloc三者的差别
1.malloc 作用:分配内存块 原型:void *malloc(size_t size);size表示要分配的字节数 返回值:返回一个指向所分配空间的void指针,假设没有足够的内存可用,则返回N ...
- 使用autoCompleteTextView以及MultiAutoCompleteTextView实现自动匹配输入内容
一:autoCompleteTextView 1:控件属性设置: 注意添加:android:completionThreshold="1"来设置输入几个字符的时候开始显示匹配的内容 ...
- 解决虚拟内存不够导致Eclipse is not responding
安装目录下eclipse.ini中: 修改参数至必要大小. e.g. -vmargs-Djava.net.preferIPv4Stack=true-Dosgi.requiredJavaVersion= ...
- JS拖动DIV布局
方法一: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
- PHP学习笔记9-生成图片
用PHP代码在网页上生成图片 <?php /** * Created by PhpStorm. * User: Administrator * Date: 2015/6/29 * Time: 2 ...
- Laravel 5.1 ACL权限控制 一
请自行添加命名空间,代码下载地址 https://github.com/caoxt/learngit 1.所需要用到的数据表 users(用户表).roles(角色表).role_user(用户角色对 ...