HDU 4609 FFT+组合数学
3-idiots
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7804 Accepted Submission(s): 2724
However, the three men were exactly idiots, and what they would do is only to pick the branches randomly. Certainly, they couldn't pick the same branch - but the one with the same length as another is available. Given the lengths of all branches in the forest, determine the probability that they would be saved.
Each test case begins with the number of branches N(3≤N≤105).
The following line contains N integers a_i (1≤a_i≤105), which denotes the length of each branch, respectively.
解析 问n个木棍任取三个能构成三角形的概率 毫无疑问一共有n*(n-1)*(n-2) / 6 种
我们把木棍的长度计下数得到一个数组 num[ i ] 表示长度为i的木棍有多少个 第一组数据就是 num= { 0 , 1 , 0 , 2 , 1 }
我们将它看成多项式的系数 自身相乘一下得到{ 0 , 1 , 0 , 2 , 1 } *{ 0 , 1 , 0 , 2 , 1 } ={0 , 0 , 1 , 0 , 4 , 2 , 4 , 4 , 1 }= 新的num
这个结果的意义如下:
从{1 3 3 4}取一个数,从{1 3 3 4}再取一个数
取两个数和为 2 的取法是一种:1+1
和为 4 的取法有四种:1+3, 1+3 ,3+1 ,3+1
和为 5 的取法有两种:1+4 ,4+1;
和为 6的取法有四种:3+3,3+3,3+3,3+3,3+3
和为 7 的取法有四种: 3+4,3+4,4+3,4+3
和为 8 的取法有 一种:4+4
其中有重复的 我们去重一下
首先 一根木棍只能用一次 所以和为 a[i]*2的方案数多算了一次 num[ a[i]*2] ] -1
其次 1 3 3 1 是一个组合 但是算了两次 所以每一个num[ i ] / = 2 然后前缀和
每个数的权值在【1,1e5】 FFT可以在nlogn时间内解决多项式乘法
解决完上面的问题后 开始计数
我没按照从小到大将木棍排序 然后枚举第 i 根木棍为能组成的三角形最长的那一根 那么两边之和大于第三边 满足的应该有这么多种 sum[ len] -sum[ a[i] ] (len为和的最大值)
但是里面有不满足的
1 再取的两个木棍 一个大于a[i] 一个小于a[i] (大小指的是下标)
2 再取的两个木棍都大于a[i]
3 再取的两个木棍包含a[i]
这样算一下就好了
AC代码
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
using namespace std;
typedef long long ll;
typedef complex<double> complexd;
const ll maxn=3e5+,inf=0x3f3f3f3f;
const ll mod=1e9+;
const double PI = acos(-1.0);
/*
* 进行FFT和IFFT前的反转变换。
* 位置i和 (i二进制反转后位置)互换
* len必须取2的幂
*/
void change(complexd *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
*/
void fft(complexd *y,int len,int on)
{
change(y,len);
for(int h = ; h <= len; h <<= )
{
complexd wn(cos(-on**PI/h),sin(-on**PI/h));
for(int j = ; j < len; j+=h)
{
complexd w(,);
for(int k = j; k < j+h/; k++)
{
complexd u = y[k];
complexd 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]=complexd(y[i].real()/len,y[i].imag());
}
complexd x[maxn];
int a[maxn];
ll num[maxn],sum[maxn];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
fillchar(num,);
fillchar(sum,);
scanf("%d",&n);
int maxx=-;
for(int i=;i<n;i++)
{
scanf("%d",&a[i]);
num[a[i]]++;
maxx=max(maxx,a[i]);
}
int len = , len1 = maxx+, len2 = maxx+;
while(len<len1+len2+)
len <<= ;
for(int i=;i<=maxx;i++)
x[i]=complexd((double)num[i],);
for(int i=maxx+;i<len;i++)
x[i]=complexd(,);
fft(x, len, );
for(int i = ; i < len; i++)
x[i] = x[i] * x[i];
fft(x, len, -);
for(int i=;i<len;i++)
num[i]=(ll)(x[i].real()+0.5);
sort(a,a+n);
for(int i=;i<n;i++)
num[a[i]+a[i]]--;
for(int i=;i<len;i++)
sum[i]=sum[i-]+num[i]/;
ll ans=;
for(int i=;i<n;i++)
{
ll temp=sum[len-]-sum[a[i]];
temp-=1ll*i*(n-i-); //一大一小 组合情况
temp-=1ll*(n-i-)*(n-i-)/; //两个大的 组合情况
temp-=n-; //包含自己的情况
ans+=temp;
}
printf("%.7f\n",ans*6.0/((double)n*(n-)*(n-)));
}
return ;
}
HDU 4609 FFT+组合数学的更多相关文章
- HDU 4609 3-idiots (组合数学 + FFT)
题意:给定 n 条边,问随机选出 3 条边,能组成三角形的概率是多少. 析:答案很明显就是 能组成三角形的种数 / (C(n, 3)).现在的问题是怎么求能组成三角形的种数. 这个博客说的非常清楚了 ...
- HDU 4609 FFT模板
http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:给你n个数,问任意取三边能够,构成三角形的概率为多少. 思路:使用FFT对所有长度的个数进行卷积(\ ...
- hdu 4609 FFT
题意:给出一堆数,问从这些数中取3个能组成三角形的概率? sol:其实就是问从这些数里取3个组成三角形有多少种取法 脑洞大开的解法:用FFT 设一开始的数是1 3 3 4 作一个向量x,其中x[i]= ...
- HDU 4609 FFT+各种分类讨论
思路: http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html 其实我是懒得写了.... 一定要define int long ...
- hdu 4609 3-idiots [fft 生成函数 计数]
hdu 4609 3-idiots 题意: 给出\(A_i\),问随机选择一个三元子集,选择的数字构成三角形的三边长的概率. 一开始一直想直接做.... 先生成函数求选两个的方案(注意要减去两次选择同 ...
- hdu 4609 3-idiots
http://acm.hdu.edu.cn/showproblem.php?pid=4609 FFT 不会 找了个模板 代码: #include <iostream> #include ...
- 快速傅里叶变换应用之二 hdu 4609 3-idiots
快速傅里叶变化有不同的应用场景,hdu4609就比较有意思.题目要求是给n个线段,随机从中选取三个,组成三角形的概率. 初始实在没发现这个怎么和FFT联系起来,后来看了下别人的题解才突然想起来:组合计 ...
- hdu 5830 FFT + cdq分治
Shell Necklace Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- hdu 5885 FFT
XM Reserves Time Limit: 10000/10000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)T ...
随机推荐
- webapi之fiddler头设置
Host: localhost:16648Connection: keep-aliveContent-Length: 36Accept: application/json, text/javascri ...
- codevs 1422 河城荷取
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 在幻想乡,河城荷取是擅长高科技工业的河童.荷取的得意之作除了光学迷彩外,还有 ...
- 洛谷 P1955 程序自动分析
题目描述 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变 ...
- OFDM、FTTx、SCTP、Ad Hoc、WSN术语简介
上课提到一些术语,下来查了一下,总结在这里. OFDM: OFDM(Orthogonal Frequency Division Multiplexing)即正交频分复用技术,实际上OFDM是MCM(M ...
- Dreamoon and MRT
Dreamoon and MRT 题目链接: http://codeforces.com/group/gRkn7bDfsN/contest/212299/problem/B 只需要考虑相对位置,设a0 ...
- myBatis的binding错误:Invalid bound statement (not found)
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误这个问题我找了好久,终于找到了正确的写 ...
- 什么是JavaScript框架-------share
摘要:现代网站和web应用程序趋向于依赖客户端的大量的javascript来提供丰富的交互.特别是通过不刷新页面的异步请求来返回数据或从服务器端的脚本(或数据系统)中得到响应.在这篇文章中,你将会了解 ...
- 【简●解】POJ 1185,LG P2704【炮兵阵地】
POJ 1185,LG P2704[炮兵阵地] 状压经典入门. [传送门] POJ 1185 洛谷 P2704 [题目大意] 司令部的将军们打算在 \(N\times M\) 的网格地图上部署他们的炮 ...
- PowerShell(PHPStorm terminal with PowerShell)运行git log中文乱码
解决方案: 1)以管理员身份运行PowerShell 2)新建一个针对PowerShell的Pofile文件 New-Item -Path $Profile -ItemType file -Force ...
- POJ-1163 递推
代码很容易看明白,就不详解了. 这个是空间优化的代码. #include <iostream> #include <algorithm> #define MAX 101 usi ...