• bzoj3513


    给定n个长度分别为$a_i$的木棒,问随机选择3个木棒能够拼成三角形的概率。

    $a_i$和$n$都在$10^5$以内

    对于每一个i,我们统计比i短的边有多少组合能组成长度<=i的

    用1减去这个概率就是能拼成的概率

    具体就是用sum[i]表示i出现的次数

    sum[i]可以转化成如下卷积的样子

    $$sum[i] = sum_{j=1}^{i-1}sum[j] * sum[i - j - 1]$$

    然后FFT

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 300010;
    const double pi = acos(-1.0);
    struct Cint
    {
        double r,i;
        Cint() {r = i = 0.00;}
        Cint(double _r,double _i) : r(_r),i(_i){}
        Cint operator + (const Cint &b)const{return Cint(r + b.r,i + b.i);}
        Cint operator - (const Cint &b)const{return Cint(r - b.r,i - b.i);}
        Cint operator * (const Cint &b)const{return Cint(r * b.r - i * b.i,i * b.r + r * b.i);}
    }s[maxn];
    int a[maxn],LEN,n;
    LL sum[maxn],ans;
    inline void FFT_init(Cint *a,int len)
    {
        for(int i = 1,j = len >> 1,k;i < len - 1;i++)
        {
            if(i < j)swap(a[i],a[j]);k = len;
            while(j >= (k>>=1)) j -= k;  
            if(j <= k) j += k;
        }
    }
    inline void FFT(Cint *a,int len,int f)
    {
        FFT_init(a,len);int l,i,j,k;Cint u,v;
        for(l = 2;l <= len;l <<= 1)
        {
            i = l >> 1;
            Cint w(cos(-f * 2 * pi / l),sin(-f * 2 * pi / l));
            for(j = 0;j ^ len;j += l)
            {
                Cint wn(1.0,0.0);
                for(k = j;k ^ (i + j);k++)
                {
                    u = a[k]; v = wn * a[i + k];
                    a[k] = u + v;a[k + i] = u - v;
                    wn = w * wn;
                }
            }
        }
        if(f == -1)
            for(i = 0;i < len;i++)a[i] . r /= len;
    }
    
    int main()
    {
        //freopen("ou.txt","r",stdin);
        //freopen("x.txt","w",stdout);
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);int mx = 0;ans = 0;
            for(int i=0;i<=LEN + 1;i++)s[i] = Cint(0.0,0.0);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                mx = max(mx,a[i]);
            }
            for(LEN = 1;(LEN >> 1) < mx;LEN <<= 1);
            for(int i=1;i<=n;i++)s[a[i]].r += 1.0;
            FFT(s,LEN,1);
            for(int i=0;i<LEN;i++)s[i] = s[i] * s[i];
            FFT(s,LEN,-1);
            for(int i=1;i<=n;i++)s[a[i] * 2].r -= 1.0;
            for(int i=1;i<=LEN;i++)sum[i] = sum[i-1] + floor(s[i].r + 0.5);
            for(int i=1;i<=n;i++)ans += sum[a[i]];
            double pos = 3.0 * ans / n / (n - 1) / (n - 2);
            printf("%.7lf
    ",1.0 - pos);
        }
    }
    View Code
  • 相关阅读:
    华为软件开发云评测
    个人技术博客(α)
    结对第二次作业
    结对第一次作业----部门通
    数独设计
    2017软件工程实践第一次作业
    Alpha冲刺博客集
    个人作业——软件工程实践总结作业
    用户使用调查报告
    总结随笔(Beta)
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/8982090.html
Copyright © 2020-2023  润新知