DU 4609 3-idiots FFT
题意还是比较好懂。
给出若干个木棍的长度,问这些木棍构成三角形的可能性。
那么公式很容易知道
就是这些木棍组成三角形的所有情况个数 除以 从n个木棍中取3个木棍的情况数量C(n, 3) 即可
但是很显然分子不太好求。 因为木棍数据量是n^5
暂时没有办法,于是看到木棍的边长,数据量也是10^5,似乎预示着什么
那么我们可不可以这样:根据三角形的性质,两边之和大于第三边。我们就枚举每个木棍,假设该木棍是三角形中的最大边,然后看剩下的能构成三角形的两边的和有多少种情况。
这样一转换思路,就转到了求给出俩数组,然后从两个数组中各取出一个数,求相加的和各自有多少种。
由于数据量是10^5 ,所以我们可以把这两个数组中各个数的个数分别用数组num1, num2存起来。 然后刚才求相加的和有多少种就变成了求num1数组和num2之间的卷积了。
这就转变成了FFT了。 这样一来复杂度就降到了nlogn,到达了可以接受的范围
然后kuangbin巨巨的解释非常详细,我也是看了他的才懂点。http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html
然后就是代码了。 胡骏巨巨的模板果然厉害!!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
#define L(x) (1 << (x))
const double PI = acos(-1.0);
const int Maxn = 400001;
double ax[Maxn], ay[Maxn], bx[Maxn], by[Maxn];
long long num[Maxn];
int a[Maxn/4];
long long sum[Maxn];
int revv(int x, int bits)
{
int ret = 0;
for (int i = 0; i < bits; i++)
{
ret <<= 1;
ret |= x & 1;
x >>= 1;
}
return ret;
}
void fft(double * a, double * b, int n, bool rev)
{
int bits = 0;
while (1 << bits < n) ++bits;
for (int i = 0; i < n; i++)
{
int j = revv(i, bits);
if (i < j)
swap(a[i], a[j]), swap(b[i], b[j]);
}
for (int len = 2; len <= n; len <<= 1)
{
int half = len >> 1;
double wmx = cos(2 * PI / len), wmy = sin(2 * PI / len);
if (rev) wmy = -wmy;
for (int i = 0; i < n; i += len)
{
double wx = 1, wy = 0;
for (int j = 0; j < half; j++)
{
double cx = a[i + j], cy = b[i + j];
double dx = a[i + j + half], dy = b[i + j + half];
double ex = dx * wx - dy * wy, ey = dx * wy + dy * wx;
a[i + j] = cx + ex, b[i + j] = cy + ey;
a[i + j + half] = cx - ex, b[i + j + half] = cy - ey;
double wnx = wx * wmx - wy * wmy, wny = wx * wmy + wy * wmx;
wx = wnx, wy = wny;
}
}
}
if (rev)
{
for (int i = 0; i < n; i++)
a[i] /= n, b[i] /= n;
}
} int solve(long long a[], int na, long long ans[])
{
int len = na, ln;
for(ln = 0; L(ln) < na; ++ln);
len=L(++ln);
for(int i = 0; i < len; ++i)
{
if (i >= na) ax[i] = 0, ay[i] = 0;
else ax[i] = a[i], ay[i] = 0;
}
fft(ax, ay, len, 0);
for(int i=0; i<len; ++i)
{
double cx = ax[i] * ax[i] - ay[i] * ay[i];
double cy = 2 * ax[i] * ay[i];
ax[i] = cx, ay[i] = cy;
}
fft(ax, ay, len, 1); for(int i=0; i<len; ++i)
ans[i] = ax[i] + 0.5;
return len;
} int main()
{
int T;
int n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(num, 0, sizeof(num));
for(int i = 0;i < n;i++)
{
scanf("%d", &a[i]);
num[a[i]]++;
}
sort(a, a + n);
int len1 = a[n - 1] + 1;
solve(num, len1, num);
int len = 2 * a[n - 1];
for(int i = 0;i < n;i++) //减掉取两个相同的组合
num[a[i] + a[i]]--; for(int i = 1;i <= len;i++) //选择的无序,除以2
num[i] /= 2;
sum[0] = 0;
for(int i = 1;i <= len;i++)
sum[i] = sum[i - 1] + num[i];
long long cnt = 0;
for(int i = 0;i < n; i++)
{
cnt += sum[len] - sum[a[i]];
cnt -= (long long)(n - 1 - i) * i;//减掉一个取大,一个取小的
cnt -= (n - 1); //减掉一个取本身,另外一个取其它
cnt -= (long long)(n - 1 - i)*(n - i - 2) / 2; //减掉大于它的取两个的组合
}
//总数
long long tot = (long long)n * (n - 1) * (n - 2) / 6;
printf("%.7lf\n",(double)cnt / tot);
}
return 0;
}
DU 4609 3-idiots FFT的更多相关文章
- bzoj 3513: [MUTC2013]idiots FFT
bzoj 3513: [MUTC2013]idiots FFT 链接 bzoj 思路 参考了学姐TRTTG的题解 统计合法方案,最后除以总方案. 合法方案要不好统计,统计不合法方案. \(a+b< ...
- HDU 4609 3-idiots(FFT)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:给出n个正整数(数组A).每次随机选出三个数.问这三个数能组成三角形的概率为多大? 思路: ...
- bzoj 3513 [MUTC2013]idiots FFT 生成函数
[MUTC2013]idiots Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 806 Solved: 265[Submit][Status][Di ...
- HDU 4609 3-idiots (组合数学 + FFT)
题意:给定 n 条边,问随机选出 3 条边,能组成三角形的概率是多少. 析:答案很明显就是 能组成三角形的种数 / (C(n, 3)).现在的问题是怎么求能组成三角形的种数. 这个博客说的非常清楚了 ...
- BZOJ3513[MUTC2013]idiots——FFT+生成函数
题目描述 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. 输入 第一行T(T<=100),表示数据组数. 接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个 ...
- [MUTC2013][bzoj3513] idiots [FFT]
题面 传送门 思路 首先有一个容斥原理的结论:可以组成三角形的三元组数量=所有三元组-不能组成三角形的三元组 也就是说我们只要求出所有不能组成三角形的三元组即可 我们考虑三元组(a,b,c),a< ...
- 【bzoj3513】[MUTC2013]idiots FFT
题目描述 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. 输入 第一行T(T<=100),表示数据组数. 接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个 ...
- HDU 4609 3-idiots ——(FFT)
这是我接触的第一个关于FFT的题目,留个模板. 这题的题解见:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html. FFT的 ...
- hdu 4609: 3-idiots (FFT)
题目链接 题意:从N个数中,选出三个两两不同的数,求这三个数能够作为一个三角形的三边长的概率. 题解:用一个数组num[]记录大小为 i 的数出现的次数,通过 num[] 卷 num[] 得到 num ...
随机推荐
- c语言循环链表的问题
今天,老师说了一道题,大意是,有一群小朋友10个人,但是老师只有一个苹果,只能给一个小朋友,于是老师就决定让小朋友们做成一圈,从第一个小朋友开始,每隔一个小朋友就没有机会得到苹果,最后剩下的一个人可以 ...
- BC-NFS安装依赖
[root@BC-NFS01 glusterFS_installer]# sh install_local.sh 18-09-19 22:43:28 [install_local.sh] INFO : ...
- linux 下rocketmq安装
一.解压mq(/data下)tar -zxvf Rocketmq-3.5.8.tar.gz 二.修改配置文件vi /etc/profileexport rocketmq=/data/alibaba-r ...
- 机器学习之路: python线性回归 过拟合 L1与L2正则化
git:https://github.com/linyi0604/MachineLearning 正则化: 提高模型在未知数据上的泛化能力 避免参数过拟合正则化常用的方法: 在目标函数上增加对参数的惩 ...
- SQLSERVER2014集群实战——IP引发的坑
在之前的帖子里有提到过,为了避免IP变更带来的一系列问题,采取了不改变IP的策略.原以为,只要SQLSERVER的群集IP保持与之前单机部署的IP一致,就基本上不会有问题.然而实际永远比预想的更复杂. ...
- CF17E Palisection 差分+manacher算法
题目大意: 给定一个串$S$,询问有多少对相交的回文子串 直接做的办法: 我们先考虑求出以$i$为结尾的串的数量,这个很好统计 之后,我们再求出所有包含了点$i$的回文串的数目 这个相当于在$i$的左 ...
- Windows Server 2008 R2的web服务器nginx和Apache的比较
因为很喜欢nginx,所以也想尝试在Windows下使用nginx,前面安装配置都挺顺利,把域名解析尽量后,通过域名代理访问jboss,却异常的慢,起码有3秒的时间才显示页面,而这个页面是jboss的 ...
- bzoj 4237: 稻草人 -- CDQ分治
4237: 稻草人 Time Limit: 40 Sec Memory Limit: 256 MB Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行 ...
- setTimeout 第一个参数类型
读别人代码的时候看到这么一段,很不理解,然后就搜了一下百度 setTimeout / setInterval 第一个参数可以有三种类型: 字符串 . methods . 匿名函数 1.字符串 ...
- LR监控Apache资源
前提本文使用的是lampp环境下自带的Apache服务 步骤1.修改Apache中Httpd.conf文件,添加如下代码:文件位置为:/opt/lampp/etc/httpd.conf,如下图: &l ...