zoukankan      html  css  js  c++  java
  • HDU 4609 3-idiots

    HDU - 4609

    思路:
    记录每个木棍长度出现的次数,然后就可以用用类似多项式的乘法(专业术语:卷积,因为是下标和为一特定值的积的和(x+y=k),相当于在笛卡尔坐标系中将这条直线卷起来,故得名卷积)的方法计算两个组合后每个长度的木棍的个数,然后用容斥减去多余的。

    然后对它求个前缀和sum

    假设两个组合最长木棍为l

    然后再枚举n个木棍,假设当前的ai为最大的木棍,

    另外两个木棍的和肯定大于ai,所以方案数加sum[l] - sum[ai]

    减去另外两个都大于它的情况,也就是减去(n-i-1)*(n-i-2)/2

    减去一大一小的情况,也就是减去i*(n-i-1)

    减去一个为本身,一个为其他的情况,也就是减去n-1

    最后拿方案数除以所有的情况n*(n-1)*(n-2)/6

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    #define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pii pair<int, int>
    #define piii pair<int,pii>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
    //head
    
    const int N = 4e5 + 10;
    int a[N], R[N];
    LL num[N],sum[N];
    struct Complex {
        double x, y;
        Complex(double _x=0, double _y=0) : x(_x),y(_y) {};
        Complex operator + (Complex &t) {return Complex(x+t.x, y+t.y);}
        Complex operator - (Complex &t) {return Complex(x-t.x, y-t.y);}
        Complex operator * (Complex &t) {return Complex(x*t.x - y*t.y, x*t.y + y*t.x);}
    }X[N];
    void fft(Complex *x, int n, int type) {
        for (int i = 0; i < n; i++) if(i < R[i]) swap(x[i], x[R[i]]);
        for (int i = 1; i < n; i<<=1) {
            Complex wn(cos(pi/i), type*sin(pi/i));
            for (int j = 0; j < n; j+=i<<1) {
                Complex w(1, 0);
                for (int k = 0; k < i; k++, w=w*wn) {
                    Complex X = x[j+k];
                    Complex Y = w*x[j+k+i];
                    x[j+k] = X + Y;
                    x[j+k+i] = X - Y;
                }
            }
        }
    }
    int main() {
        int T, n;
        scanf("%d", &T);
        while(T--) {
            mem(num, 0);
            scanf("%d", &n);
            for (int i = 0; i < n; i++) scanf("%d", &a[i]), num[a[i]]++;
            sort(a, a+n);
            int len = a[n-1] + 1;
            int l = 1, L = 0;
            for (int i = 0; i < len; i++) X[i] = Complex(num[i], 0);
            for ( ; l < len*2; l <<= 1) L++;
            for (int i = len; i < l; i++) X[i] = Complex(0, 0);
            for (int i = 0; i < l; i++) {
                R[i] = (R[i>>1]>>1)|((i&1)<<L-1);
            }
            fft(X, l, 1);
            for (int i = 0; i < l; i++) X[i] = X[i]*X[i];
            fft(X, l, -1);
            for (int i = 0; i < l; i++) num[i] = (LL)(X[i].x/l + 0.5);
            for (int i = 0; i < n; i++) num[a[i]+a[i]]--; 
            for (int i = 0; i < l; i++) num[i] /= 2;
            sum[0] = num[0];
            for (int i = 1; i < l; i++) sum[i] = sum[i-1] + num[i]; 
            LL ans = 0;
            for(int i = 0; i < n; i++) {
                ans += sum[l-1] - sum[a[i]];
                ans -= 1LL * (n-i-1) * i;
                ans -= 1LL * (n-i-1) * (n-i-2) / 2;
                ans -= n-1;
            } 
            LL t = 1LL*n*(n-1)*(n-2)/6;
            printf("%.7f
    ", (double)ans/t);
        }
        return 0;
    }

    PS:长度可以扩展一点,后面是0都没关系,只要长度是2的幂次就可以

  • 相关阅读:
    css3 box-sizing盒模型
    数字递增组件
    设置视频水平垂直居中显示在页面上
    修改placeholder样式,兼容多个浏览器
    一款还不错的日期插件layDate
    vue-cli打包后出现 “Uncaught SyntaxError: Unexpected token <”这个错
    详谈C++虚函数表那回事(一般继承关系)
    C++多态的实现及原理详细解析
    位运算求两个数的平均值
    网页设计入门<一>
  • 原文地址:https://www.cnblogs.com/widsom/p/9155012.html
Copyright © 2011-2022 走看看