题意:给出一堆数,问从这些数中取3个能组成三角形的概率?

sol:其实就是问从这些数里取3个组成三角形有多少种取法

脑洞大开的解法:用FFT

设一开始的数是1 3 3 4

作一个向量x,其中x[i]=边长为i的边的个数

那么就有x=[0 1 0 2 1 0 0 0 0]

令y=x,对x和y作DFT,得到dx和dy。令dn=dx*dy,再对dn作IDFT得到n

那么就得到n=[0 0 1 0 4 2 4 4 1 0 ]

其中n[i]=在x和y中各选一条边,使得两条边之和为i有几种方案

这时得到的n并不好,包含了各种重复的方案。还得减一下

最后得到的n=[0 0 0 0 2 1 1 2 0]

然后对n做奇怪的操作。。。

先求前缀和,得到S

对于a[i].  我们假设a[i]是形成的三角形中最长的。这样就是在其余中选择两个和>a[i],而且长度不能大于a[i]的。(注意这里所谓的大于小于,不是说长度的大于小于,其实是排好序以后的,位置关系,这样就可以不用管长度相等的情况,排在a[i]前的就是小于的,后面的就是大于的)。

根据前面求得的结果。
长度和大于a[i]的取两个的取法是sum[len]-sum[a[i]]. 但是这里面有不符合的。 一个是包含了取一大一小的
cnt -= (long long)(n--i)*i; 一个是包含了取一个本身i,然后取其它的
cnt -= (n-); 还有就是取两个都大于的了
cnt -= (long long)(n--i)*(n-i-)/;

Code:

 #include  <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
const double PI = acos(-1.0);
#define LL long long
#define MAXL 524230
#define MAXN 100010 //复数结构体
struct Complex
{
double x,y;//实部和虚部 x+yi
Complex(double _x = ,double _y = )
{
x = _x;
y = _y;
}
Complex operator -(const Complex &b)const
{
return Complex(x-b.x,y-b.y);
}
Complex operator +(const Complex &b)const
{
return Complex(x+b.x,y+b.y);
}
Complex operator *(const Complex &b)const
{
return Complex(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
/*
*进行FFT和IFFT前的反转变换。
*位置i和(i二进制反转后位置)互换
* len必须去2的幂
*/
void change(Complex y[],int len)
{
int i,j,k;
for(i = , j = len/; i <len-; i++)
{
if(i < j)swap(y[i],y[j]);
//交换互为小标反转的元素,i<j保证交换一次
//i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
k = len/;
while(j >= k)
{
j -= k;
k /= ;
}
if(j < k)j += k;
}
}
/*
*做FFT
* len必须为2^k形式,
* on==1时是DFT,on==-1时是IDFT
*/
//fft(x,len,1):对向量x做DFT(时域->频域),向量长度为1--len
//fft(x,len,-1):做IDFT(频域->时域)
void fft(Complex y[],int len,int on)
{
change(y,len);
for(int h = ; h <= len; h <<= )
{
Complex wn(cos(-on**PI/h),sin(-on**PI/h));
for(int j = ; j < len; j+=h)
{
Complex w(,);
for(int k = j; k < j+h/; k++)
{
Complex u = y[k];
Complex t = w*y[k+h/];
y[k] = u+t;
y[k+h/] = u-t;
w = w*wn;
}
}
}
if(on == -)
for(int i = ; i < len; i++)
y[i].x /= len;
} Complex x[MAXL];
LL nx[MAXL],tri[MAXN],sx[MAXL],NUM[MAXL];
int TIMES,N,tm; int main()
{
scanf("%d",&TIMES);
for (int Times=;Times<=TIMES;Times++)
{
scanf("%d",&N); memset(nx,,sizeof(nx));
memset(sx,,sizeof(sx));
memset(x,,sizeof(x));
memset(NUM,,sizeof(NUM)); for (int i=;i<N;i++)
{
scanf("%d",&tri[i]);
NUM[tri[i]]++;
} sort(tri,tri+N);
int mx=tri[N-];
int l1=mx+;
int len=;
while (len<*l1) len<<=;
for (int i=;i<l1;i++)
x[i]=Complex(NUM[i],);
for (int i=l1;i<len;i++)
x[i]=Complex(,); fft(x,len,); for (int i=;i<len;i++)
x[i]=x[i]*x[i]; fft(x,len,-);
for (int i=;i<len;i++)
nx[i]=(LL)(x[i].x+0.5); len=*mx;
for (int i=;i<N;i++)
nx[tri[i]*]--;
for (int i=;i<=len;i++)
nx[i]=nx[i]/;
/*
for (int i=0;i<=len;i++)
cout<<nx[i]<<" ";
cout<<endl;
*/
sx[]=;
for (int i=;i<=len;i++)
sx[i]=sx[i-]+nx[i];
/*
for (int i=0;i<=len;i++)
cout<<sx[i]<<" ";
cout<<endl;
*/
LL tot=;
for (int i=;i<N;i++)
{
tot+=sx[len]-sx[tri[i]];
tot-=(LL)(N-i-)*i;
tot-=(N-);
tot-=(LL)(N--i)*(N-i-)/;
}
//cout<<tot<<endl;
LL kk=(LL)(N*(N-)*(N-)/);
//cout<<tot<<" "<<kk<<endl;
printf("%.7lf\n",(double)tot/kk);
} return ;
}

ref:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html

hdu 4609 FFT的更多相关文章

  1. HDU 4609 FFT模板

    http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:给你n个数,问任意取三边能够,构成三角形的概率为多少. 思路:使用FFT对所有长度的个数进行卷积(\ ...

  2. HDU 4609 FFT+组合数学

    3-idiots Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  3. HDU 4609 FFT+各种分类讨论

    思路: http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html 其实我是懒得写了.... 一定要define int long ...

  4. hdu 4609 3-idiots [fft 生成函数 计数]

    hdu 4609 3-idiots 题意: 给出\(A_i\),问随机选择一个三元子集,选择的数字构成三角形的三边长的概率. 一开始一直想直接做.... 先生成函数求选两个的方案(注意要减去两次选择同 ...

  5. hdu 4609 3-idiots

    http://acm.hdu.edu.cn/showproblem.php?pid=4609 FFT  不会 找了个模板 代码: #include <iostream> #include ...

  6. 快速傅里叶变换应用之二 hdu 4609 3-idiots

    快速傅里叶变化有不同的应用场景,hdu4609就比较有意思.题目要求是给n个线段,随机从中选取三个,组成三角形的概率. 初始实在没发现这个怎么和FFT联系起来,后来看了下别人的题解才突然想起来:组合计 ...

  7. hdu 5830 FFT + cdq分治

    Shell Necklace Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  8. hdu 5885 FFT

    XM Reserves Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)T ...

  9. HDU 1402 FFT 大数乘法

    $A * B$ FFT模板题,找到了一个看起来很清爽的模板 /** @Date : 2017-09-19 22:12:08 * @FileName: HDU 1402 FFT 大整数乘法.cpp * ...

随机推荐

  1. DocOptimizer 0.9.0 Beta Released

    DocOptimizer 是一个文档优化工具,它通过移除Excel中多余的单元格:将嵌入的OLE替换成图片:移除文档中的隐藏信息:优化文档中的图片等等手段,将Office或PDF文件压缩20%-90% ...

  2. Android 系统稳定性 - ANR(二)(转)

    编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. 1.2 如何分析ANR问题 引起ANR问题的根本原因,总的来说可以归纳为两类: 应用进程自身引起的,例如: 主线程阻塞.挂起.死循 ...

  3. 分享我对领域驱动设计(DDD)的学习成果

    本文内容提要: 1. 领域驱动设计之领域模型 2. 为什么建立一个领域模型是重要的 3. 领域通用语言(Ubiquitous Language) 4.将领域模型转换为代码实现的最佳实践 5. 领域建模 ...

  4. Entity Framework6 with Oracle(可实现code first)

    Oracle 与2个月前刚提供对EF6的支持.以前只支持到EF5.EF6有很多有用的功能 值得升级.这里介绍下如何支持Oracle   一.Oracle 对.net支持的一些基础知识了解介绍. 1.早 ...

  5. Wabpack系列:在webpack+vue开发环境中使用echarts导致编译文件过大怎么办?

    现象,在一个webpack+vue的开发环境中,npm install echarts --save了echarts,然后在vue文件中直接使用 import echarts from 'echart ...

  6. .Net下一个类型转换神器

    引言 类型转换经常遇到,最常用的应该是string类型转换为其它基元类型,常见于http参数类型转换.Convert静态类的Convert.ChangeType()方法可以把实现IConvertibl ...

  7. 如何阻止SELECT * 语句

    我们每个人都知道是个不好的做法,但有时我们还是要这样做:我们执行SELECT * 语句.这个方法有很多弊端: 你从你的表里返回每个列,甚至后期加的列.想下如果你的查询里将来加上了VARCHAR(MAX ...

  8. “奥特曼攻打小怪兽”java学习打怪升级第一步

    ---恢复内容开始--- 练习:回合制对战游戏:奥特曼和小怪兽进行PK,直到一方的血量为0时结束战斗,输出谁胜利了! 不难看出场景中有两个对象:”奥特曼“这一对象抽象为”Ao"类:     ...

  9. Linux下解决用户不能执行sudo的方法

    报错: xxx is not in the sudoers file.  This incident will be reported. Linux默认没有为当前用户开启sudo权限! $ su  $ ...

  10. win7远程桌面连接不上,解决办法

    来源于:http://jingyan.baidu.com/article/39810a23edc48bb637fda672.html 一般情况下,对WIN7的远程连接只需要5步即可完成远程连接的设置: ...