HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1
来源:互联网 发布:三角刮刀淘宝 编辑:程序博客网 时间:2024/05/10 17:34
传送门
3-idiots
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4140 Accepted Submission(s): 1464
Problem Description
King OMeGa catched three men who had been streaking in the street. Looking as idiots though, the three men insisted that it was a kind of performance art, and begged the king to free them. Out of hatred to the real idiots, the king wanted to check if they were lying. The three men were sent to the king’s forest, and each of them was asked to pick a branch one after another. If the three branches they bring back can form a triangle, their math ability would save them. Otherwise, they would be sent into jail.
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.
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.
Input
An integer T(T≤100) will exist in the first line of input, indicating the number of test cases.
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.
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.
Output
Output the probability that their branches can form a triangle, in accuracy of 7 decimal places.
Sample Input
2
4
1 3 3 4
4
2 3 3 4
Sample Output
0.5000000
1.0000000
题目大意:
给你
解题思路:
我们现在用一个
的那一个,然后又因为是组合数,所以要除以
前边是最大的边,但是现在遇到一个问题就是可能我们多算了一些值,然后我们再进行一下去重就行了,具体的细节可以看一下 kuangbin 巨巨的博客他写的很好。
#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;const double PI = acos(-1.0);typedef long long LL;const LL MAXN = 4e5+100;struct complex { double a, b; complex(double aa = 0.0, double bb = 0.0) { a = aa; b = bb; } complex operator +(const complex &e) { return complex(a + e.a, b + e.b); } complex operator -(const complex &e) { return complex(a - e.a, b - e.b); } complex operator *(const complex &e) { return complex(a * e.a - b * e.b, a * e.b + b * e.a); }}x1[MAXN], x2[MAXN], x[MAXN];void change(complex * y, LL len){ LL i, j, k; for (i = 1, j = len / 2; i < len - 1; i++){ if (i < j) swap(y[i], y[j]); k = len / 2; while (j >= k){ j -= k; k /= 2; } if (j < k) j += k; }}void fft(complex *y, LL len, LL on){ change(y, len); for (LL h = 2; h <= len; h <<= 1){ complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h)); for (LL j = 0; j < len; j += h){ complex w(1, 0); for (LL k = j; k < j + h / 2; k++){ complex u = y[k]; complex t = w * y[k + h / 2]; y[k] = u + t; y[k + h / 2] = u - t; w = w * wn; } } } if (on == -1) for (LL i = 0; i < len; i++) y[i].a /= len;}LL a[MAXN], num[MAXN], sum[MAXN];///num[i]:长度为 i 的有 num[i] 个int main(){ int T; LL n; scanf("%d",&T); while(T--){ scanf("%lld",&n); memset(num, 0, sizeof(num)); for(LL i=0; i<n; i++){ scanf("%lld",&a[i]); num[a[i]]++; } sort(a, a+n); LL len = 1LL; LL len1 = a[n-1] + 1LL; while(len < 2*len1)len<<=1LL; ///cout<<len<<endl; for(LL i=0; i<len1; i++) x1[i].a = num[i], x1[i].b = 0; for(LL i=len1; i<len; i++) x1[i].a = 0, x1[i].b = 0; fft(x1, len, 1); for(LL i=0; i<len; i++) x[i] = x1[i] * x1[i]; fft(x, len, -1); ///fft 之后num[i] 表示的是两个长度和为 i 的个数 for(LL i=0; i<len; i++) num[i] = (LL)(x[i].a+0.5); for(LL i=0; i<n; i++)///去重 num[a[i]*2]--; for(LL i=0; i<len; i++)///是两个数的组合应该除以2 num[i]>>=1LL; sum[0] = 0;///sum[i]: 前缀和 sum[len-1]-sum[i]:长度和 > i 的 for(LL i=1; i<len; i++) sum[i] = sum[i-1] + num[i]; double ans = 0, tmp = sum[len-1]; for(LL i=0; i<n; i++){ ///长度和 > a[i] 的 ans += tmp - sum[a[i]]; ///a[i] 是第二大的 ans -= (n-1-i)*i; ///包含 a[i] 的,从(n-1)个中任选一个 ans -= (n-1); ///a[i] 是最小的,从后面两个选两个 ans -= (n-1-i)*(n-1-i-1)/2; } double tp = n*(n-1)*(n-2)/6; printf("%.7f\n",ans/tp); } return 0;}
0 0
- HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1
- HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1
- [HDU 4609] 3-idiots (计数+FFT优化卷积)
- hdu 4609 3-idiots (FFT+计数)
- HDU 4609 3-idiots(FFT,计数)
- HDU 4609 3-idiots(多项式计数 + FFT卷积优化)
- 计算几何(组合计数+向量排序)——Eureka ( HDU 5738 ) ( 2016 Multi-University Training Contest 2 1005 )
- 2013 Multi-University Training Contest 1——I-number
- 2013 Multi-University Training Contest 1 (hdu 4601 hdu 4603)
- hdu 5752 Sqrt Bo(2016 Multi-University Training Contest 3——水题)
- hdu 5753 Permutation Bo(2016 Multi-University Training Contest 3——组合)
- HDU 5755 Gambler Bo(高斯消元裸题)——2016 Multi-University Training Contest 3
- HDU 5319 Painter(模拟 + 规律)——2015 Multi-University Training Contest 3
- hdu 5733 tetrahedron(2016 Multi-University Training Contest 1——几何公式题)
- HDU 5288 OO’s Sequence(数学)——2015 Multi-University Training Contest 1
- HDU 4609 3-idiots FFT+计数问题
- hdu 4609 3-idiots FFT 计数
- hdu 4609 3-idiots [FFT计数]【数学】
- 给大家发一个linux下vim的很好用的配置文件
- AndroidFire,一款新闻阅读 App
- iOS判断点是否在多边形面内(高德地图开发)
- MyBatis
- HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1
- HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1
- xshell终端传输文件
- JAVA学习日记08
- centos7防火墙开放80端口
- css 使用background背景实现border边框效果
- 顶级的JavaScript框架、库、工具及其使用
- FreeBook 基于 MVP 模式开发的带缓存网络爬虫,采用最流行框架搭建,干货多多
- Altium Designer Bottom Solder层的作用
- 微信公众号开发Apache+php如何搭建服务