题目大意:

给出n(1e5)条线段(长度为整数,<=1e5),求任取3条线段能组成一个三角形的概率。

用cnt[i]记录长度为i的线段的个数,通过卷积可以计算出两条线段长度之和为i的方案数sum[i]:先用FFT计算出cnt[i]的卷积sum[i],为取两条线段长度和为i的排列数(包括自己和自己),去掉自己和自己的方案数,再对所有sum[i]除以2即为所求方案数。

之后对所有线段a[i]有大到小排列,考虑第i条线段是三角形最长边的情况(长度相同则将编号大的视为更长,就没有长度相同的情况了。实际计算时无影响)。首先是sum[i + 1] + sum[i + 2] + ... + sum[len - 1],即其他两边之和要大于他的方案数。然后去掉:1.另两边有一条比他大,有一条比他小。 2.两条都比他长。 3.有一条是他自己。这三种情况。

要注意有些地方爆int。还有len的计算要注意边界(一直wa,wa了半天)。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std; const double pi = acos(-); struct Complex{
double real, imag;
Complex (){}
Complex (double _real, double _imag){
real = _real;
imag = _imag;
}
}; Complex operator + (Complex x, Complex y){
return Complex(x.real + y.real, x.imag + y.imag);
} Complex operator - (Complex x, Complex y){
return Complex(x.real - y.real, x.imag - y.imag);
} Complex operator * (Complex x, Complex y){
return Complex(x.real * y.real - x.imag * y.imag, x.real * y.imag + x.imag * y.real);
} Complex operator / (Complex x, double y){
return Complex(x.real / y, x.imag / y);
} int reverse(int x, int len){
int t = ;
for (int i = ; i < len; i <<= ){
t <<= ;
if (x & i) t |= ;
}
return t;
} Complex A[];
void FFT(Complex *a, int n, int DFT){
for (int i = ; i < n; ++i) A[reverse(i, n)] = a[i];
for (int i = ; i <= n; i <<= ){
Complex wn = Complex(cos( * pi / i), DFT * sin( * pi / i));
for (int j = ; j < n; j += i){
Complex w = Complex(, );
for (int k = ; k < (i >> ); ++k){
Complex x = A[j + k];
Complex y = w * A[j + k + (i >> )];
A[j + k] = x + y;
A[j + k + (i >> )] = x - y;
w = w * wn;
}
}
}
if (DFT == -) for (int i = ; i < n; ++i) A[i] = A[i] / n;
for (int i = ; i < n; ++i) a[i] = A[i];
} int T, n;
int a[];
int cnt[];
Complex B[];
long long sum[]; int main(){ scanf("%d", &T);
while (T--){
scanf("%d", &n);
int maxL = ;
memset(cnt, , sizeof(cnt));
memset(sum, , sizeof(sum));
for (int i = ; i < n; ++i){
scanf("%d", a + i);
if (a[i] > maxL) maxL = a[i];
++cnt[a[i]];
}
int len = ;
while (len <= maxL * ) len <<= ;
for (int i = ; i <= maxL; ++i) B[i] = Complex(cnt[i], );
for (int i = maxL + ; i < len; ++i) B[i] = Complex(, );
FFT(B, len, );
for (int i = ; i < len; ++i) B[i] = B[i] * B[i];
FFT(B, len, -);
for (int i = ; i < len; ++i) sum[i] = (long long)(B[i].real + 0.5);
for (int i = ; i < n; ++i) --sum[a[i] + a[i]];
for (int i = ; i < len; ++i) sum[i] >>= ;
for (int i = len - ; i >= ; --i) sum[i] += sum[i + ];
sort(a, a + n);
long long ans = ;
for (int i = ; i < n; ++i){
long long tmp = sum[a[i] + ];
tmp -= ((long long)n - i - ) * i;
tmp -= ((long long)n - i - ) * (n - i - ) / 2LL;
tmp -= n - ;
ans += tmp;
}
double Ans = (double)ans * 6.0 / n / (n - ) / (n - );
printf("%.7f\n", Ans);
} return ;
}

HDU4609 计数问题+FFT的更多相关文章

  1. 3-idiots hdu4609 母函数+FFT 组合数学题

    http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:1e5个数,求取三个数能形成三角形的概率. 题解(这怎么会是fft入门题QAQ): 概率的算法就是三 ...

  2. HDU4609:3-idiots(FFT)

    Description Input Output Sample Input Sample Output Solution 题意:给你$n$根木棍,问你任选三根能构成三角形的概率是多少. 写挂sb细节心 ...

  3. [HDU4609] 3-idiots FFT+计数

    用FFT再去重计算出两条边加起来为某个值得方案数,然后用总方案数减去不合法方案数即可. #include<iostream> #include<cstdio> #include ...

  4. HDU4609 & FFT

    关于这道题请移步kuangbin爷的blog:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html 感觉我一辈子也不能写出这么 ...

  5. [HDU4609]3-idiots(生成函数+FFT)

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

  6. HDU-4609(FFT/NTT)

    HDU-4609(FFT/NTT) 题意: 给出n个木棒,现从中不重复地选出3根来,求能拼出三角形的概率. 计算合法概率容易出现重复,所以建议计算不合法方案数 枚举选出的最大边是哪条,然后考虑剩下两条 ...

  7. HDU4609 FFT+组合计数

    HDU4609 FFT+组合计数 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意: 找出n根木棍中取出三根木棍可以组成三角形的概率 题解: ...

  8. HDU4609 3-idiots(母函数 + FFT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4609 Description King OMeGa catched three men wh ...

  9. 【hdu4609】 3-idiots FFT

    题外话:好久没写blog了啊-- 题目传送门 题目大意:给你m条长度为ai的线段,求在其中任选三条出来,能构成三角形的概率.即求在这n条线段中找出三条线段所能拼出的三角形数量除以$\binom{m}{ ...

随机推荐

  1. HBuilder/Mui开发ios使用上拉刷新导致滚动条无法使用的解决方法

    HBuilder/Mui开发的APP使用上拉刷新,当滚动到底部是会触发上拉刷新,加载更多数据.但是ios上确是一个坑,导致滚动条无法滚动. 解决方法 放弃Mui的上拉刷新,自己使用JS实现. var ...

  2. 二、latex简单使用

    安装成功则可显示如图所示的信息. 用记事本便可完成整个过程. 命令如图所示: 首先用documentclass命令引入一个文档类,比如引入article文档类,主要用于撰写论文.{}中的内容表示命令的 ...

  3. POJ 1986 Distance Queries(LCA Tarjan法)

    Distance Queries [题目链接]Distance Queries [题目类型]LCA Tarjan法 &题意: 输入n和m,表示n个点m条边,下面m行是边的信息,两端点和权,后面 ...

  4. python assert断言函数

    python assert断言是声明布尔值必须为真的判定,如果发生异常就说明表达式为假. 可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常. self ...

  5. WebForm跨页面传值取值、C#服务端跳转页面、 Button的OnClientClick属性和超链接点击弹出警示框

    一.跨页面传值和取值: 1.QueryString - url传值,地址传值 优缺点:不占用服务器内存:保密性差,传递长度有限. 通过跳转页面路径进行传值方式: href="地址?key=v ...

  6. <转>jmeter(二十三)分布式测试

    本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...

  7. 《CSS世界》读书笔记(二)

    <!-- <CSS世界> 张鑫旭著  --> 块级元素:水平流上只能单独显示一个元素 <li>元素默认的display值是list-item,是块级元素 块级盒子( ...

  8. 利用ueditor保存到mysql数据库时出现乱码

    首先反复检查页面的字符编码,发现使用的都是 utf-8,再次检查数据库编码格式也用的是UTF-8.用format函数进行格式化,还是不起作用,最用把出现乱码的字段的数据类型由BLOB改成MEDIUMT ...

  9. UUID简介

    UUID简介如下:1.简介UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software F ...

  10. 【 记忆网络 2 】 End-to-End Memory Network

    继上一篇:Memory Network 1. 摘要 引入了一个神经网络,在一个可能很大的外部记忆上建立了一个recurrent attention模型. 该体系结构是记忆网络的一种形式,但与该工作中的 ...