hdu 4906 3-idiots fft

题目链接

n个火柴棍取3个, 问能组成三角形的概率是多少。 kuangbin大神的博客写的很详细了..http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html

注意long long什么的就没问题了。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a) memset(a, 0, sizeof(a))
typedef complex <double> cmx;
const double PI = acos(-1.0);
const int maxn = 400005;
cmx x[maxn];
int a[maxn/4];
ll num[maxn];
void change(cmx x[], int len) {
    int i, j, k;
    for(i = 1, j = len/2; i < len - 1; i++) {
        if(i < j)
            swap(x[i], x[j]);
        k = len / 2;
        while(j >= k) {
            j -= k;
            k /= 2;
        }
        if(j < k)
            j += k;
    }
}
void fft(cmx x[], int len, int on) {
    change(x, len);
    for(int i = 2; i <= len; i <<= 1) {
        cmx wn(cos(-on * 2 * PI/i), sin(-on * 2 * PI/i));
        for(int j = 0; j < len; j += i) {
            cmx w(1, 0);
            for(int k = j; k < j + i/2; k++) {
                cmx u = x[k];
                cmx v = x[k + i/2]*w;
                x[k] = u + v;
                x[k+i/2] = u - v;
                w *= wn;
            }
        }
    }
    if(on == -1) {
        for(int i = 0; i < len; i++)
            x[i] /= len;
    }
}
int main()
{
    int t, n;
    cin>>t;
    while (t--) {
        cin>>n;
        mem(num);
        int maxx = 0;
        for (int i = 0; i < n; i++) {
            scanf("%d", a + i);
            num[a[i]]++;
            maxx = max(maxx, a[i]);
        }
        sort(a, a + n);
        int len = 1;
        maxx++;
        while (len < 2*maxx) {
            len <<= 1;
        }
        for (int i = 0; i < maxx; i++) {
            x[i] = cmx(num[i], 0);
        }
        for (int i = maxx; i < len; i++) {
            x[i] = cmx(0, 0);
        }
        fft(x, len, 1);
        for (int i = 0; i < len; i++) {
            x[i] *= x[i];
        }
        fft(x, len, -1);
        for (int i = 0; i < len; i++) {
            num[i] = (ll)(x[i].real()+0.5);
        }
        for (int i = 0; i < n; i++) {
            num[a[i]+a[i]]--;
        }
        for (int i = 0; i < len; i++) {
            num[i] /= 2;
        }
        for (int i = 1; i < len; i++) {
            num[i] += num[i-1];
        }
        ll ans = 0;
        for (int i = 0; i < n; i++) {
            ans += num[len-1] - num[a[i]];
            ans -= 1LL * (n-i-1) * i;
            ans -= 1LL * (n-i-1) * (n-i-2) / 2;
        }
        ans -= 1LL * n * (n-1);
        ll sum = 1LL * n * (n-1) * (n-2) / 6;
        printf("%.7f\n", 1.0*ans/sum);
    }
    return 0;
}
时间: 2024-10-16 21:28:09

hdu 4906 3-idiots fft的相关文章

hdu 4609 3-idiots 【FFT快(gui)速傅立叶变换】

FFT实现起来挺复杂的,开始用vector,结果发现空间超了,换成数组还是超,删掉了几个后又超时了 sin cos 函数调用次数太多了,改成乘法,还是超时 最后把FFT里的除法运算和模运算优化了一下,终于过了,排的老后面 坑,3843MS,一看时间最少的只有671MS,我都怀疑这是不是同一个算法..为毛差距这么大 #pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include

HDU 4906 Our happy ending(2014 Multi-University Training Contest 4)

题意:构造出n个数 这n个数取值范围0-L,这n个数中存在取一些数之和等于k,则这样称为一种方法.给定n,k,L,求方案数. 思路:装压 每位 第1为表示这种方案能不能构成1(1表示能0表示不能)  第2为表示能不能构成2 ...  这样用d[1<<n] 的DP  像背包那样背 n次就可以 最后状态中第k位为1的就可以加上方法数. #include<cstring> #include<cstdio> #include<cmath> #include <

HDU 4906 Our happy ending (状压DP)

HDU 4906 Our happy ending 题目链接 题意:给定n个数字,每个数字可以是0-l,要选其中一些数字,然后使得和为k,问方案 思路:状压dp,滚动数组,状态表示第i个数字,能组成的数字状态为s的状态,然后每次一个数字,循环枚举它要选取1 - min(l,k)的多少,然后进行状态转移 代码: #include <cstdio> #include <cstring> typedef long long ll; const int N = (1<<20)

HDU 4906

Our happy ending Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 570    Accepted Submission(s): 183 Problem Description There is an old country and the king fell in love with a devil. The devi

hdu 4906 Our happy ending

Our happy ending Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 157    Accepted Submission(s): 39 Problem Description There is an old country and the king fell in love with a devil. The devil

hdu 4906 状压dp

/* ID: neverchanje PROG: LANG: C++11 */ #include<vector> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cstdio> #include<set> #include<queue> #includ

bzoj 3513: [MUTC2013]idiots -- FFT

3513: [MUTC2013]idiots Time Limit: 20 Sec  Memory Limit: 128 MB Description 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. Input 第一行T(T<=100),表示数据组数. 接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个数表示a_i. 3≤N≤10^5,1≤a_i≤10^5 Output T行,每行一个整数,四舍五入保留7位小数. Sample Input 2 4 1 3 3

hdu 5142 NPY and FFT

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5142 NPY and FFT Description A boy named NPY is learning FFT algorithm now.In that algorithm,he needs to do an operation called "reverse".For example,if the given number is 10.Its binary representai

hdu 4609 3-idiots (FFT+计数)

3-idiots Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2382    Accepted Submission(s): 822 Problem Description King OMeGa catched three men who had been streaking in the street. Looking as i