题目大意:

给出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. jmeter解决响应乱码

    打开apache-jmeter-2.11\bin\jmeter.properties文件,搜索“encoding”关键字,找到如下配置: # The encoding to be used if no ...

  2. 17.1-uC/OS-III消息管理(两种消息队列)

    1.使用消息队列 消息队列函数: 函数名 功能 OSQCreate() 创建一个消息队列 OSQDel() 删除一个消息队列 OSQFlush() 清空一个消息队列 OSQPend() 任务等待消息 ...

  3. JDK 1.8源码阅读 HashSet

    一,前言 类实现Set接口,由哈希表支持(实际上是一个 HashMap集合).HashSet集合不能保证的迭代顺序与元素存储顺序相同.HashSet集合,采用哈希表结构存储数据,保证元素唯一性的方式依 ...

  4. 要学的javaee技术

    mybatis.hibernate.spirng MVC.freemarker.zookeeper.dubbo.quartz的技术框架:NoSQL技术ehcache.memcached.redis等: ...

  5. 初识GitHub之创建文件

    在新建了一个项目(repository)后,会跳转到项目主页,如下图 Create new file(创建新文件)就是新建一个代码文件,Upload file(上传文件)即从内存中将代码文件上传至本项 ...

  6. 如何通过代码审计挖掘REDos漏洞

    写这篇文章的目的一是由于目前网上关于java代码审计的资料实在是太少了,本人作为一个java代码审计的新手,深知学习java代码审计的难受之处,所以将自己学习过程中挖掘的一些漏洞写成博客发出来希望可以 ...

  7. python3.x 读写文件要使用UTF8编码的话需要。。

    读写文件常遇到编码不正确的情况,都用UTF8读写文件就好了,在读写的时候加上编码格式:encoding='UTF-8'如下:with open(filename, 'r', encoding='UTF ...

  8. https://scrapingclub.com/exercise/basic_login/

    遇到的问题:csrftoken cfduid 是在request.headers里面的,一直在找怎么在scrapy里get request.header,从scrapy shell ,then fet ...

  9. AI 基础

    what AI ? 人工智能(Artificial Intelligence),英文缩写为AI. 人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的 ...

  10. Python数据分析Numpy库方法简介(三)

    补充: np.ceil()向上取整 3.1向上取整是4 np.floor()向下取整 数组名.resize((m,n)) 重置行列 基础操作 np.random.randn()符合正态分布(钟行/高斯 ...