• 【bzoj3513】[MUTC2013]idiots【FFT/NTT】


    题目传送门
    题意:给定n个长度分别为ai的木棒,问随机选择3个木棒能够拼成三角形的概率。
    题解:正面可能很不好考虑,所以我们可以反向考虑,考虑用总方案数减去无法组成三角形的方案总数。我们先构造出木棒长度的生成函数A。则选两根木棒,使得它们长度之和为x的方案总数为A2的次数为x的项的系数再减掉重复的。这个A2可以FFT求出。设a[i]为长度为i的木棍的数量之和,sum[i]为长度≥i的木棍数量之和,f[i]为选两根木棍长度为i的方案总数,maxl为选两根木棍的最大长度之和,B=A2。则显然不能形成三角形的方案总数为i=1maxlf[i]sum[i]
    如何求f[i]?
    f[i]=i0(mod2)?B[i]a[i2]:B[i]2
    i模2为0时会出现选两根长度相同的情况,共a[i/2]种长度相同的情况,所以要减去。由于B=A2,所以B的每项的系数都算了两次(比如说B次数为n的项,A的1和n-1乘起来以及A的n-1和1乘起来,这两种重复了),所以要除以二。
    最后用总方案数减去不行的方案数,再求个概率,就解决了!
    代码

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=270005;
    const double pi=3.141592653589793;
    int t,n,m,tmp,x,rev[N];
    ll tot,ans,sum[N];
    struct complex{
        double x,y;
        complex(){
            x=y=0;
        }
        complex(double x,double y):x(x),y(y){}
        friend complex operator + (const complex &a,const complex &b){
            return complex(a.x+b.x,a.y+b.y);
        }
        friend complex operator - (const complex &a,const complex &b){
            return complex(a.x-b.x,a.y-b.y);
        }
        friend complex operator * (const complex &a,const complex &b){
            return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
        }
    }a[N];
    void fft(complex *a,int dft){
        for(int i=0;i<n;i++){
            if(i<rev[i]){
                swap(a[i],a[rev[i]]);
            }
        }
        for(int i=1;i<n;i<<=1){
            complex wn=complex(cos(pi/i),dft*sin(pi/i));
            for(int j=0;j<n;j+=i<<1){
                complex w=complex(1,0),x,y;
                for(int k=j;k<j+i;k++,w=w*wn){
                    x=a[k];
                    y=w*a[k+i];
                    a[k]=x+y;
                    a[k+i]=x-y;
                }
            }
        }
        if(dft==-1){
            for(int i=0;i<n;i++){
                a[i].x/=n;
            }
        }
    }
    int main(){
        scanf("%d",&t);
        while(t--){
            tmp=0;
            memset(a,0,sizeof(a));
            memset(sum,0,sizeof(sum));
            scanf("%d",&m);
            for(int i=1;i<=m;i++){
                scanf("%d",&x);
                tmp=max(tmp,x);
                a[x].x++;
            }
            for(int i=tmp;i>=1;i--){
                sum[i]=sum[i+1]+a[i].x;
            }
            for(n=1;n<=2*tmp+1;n<<=1);
            for(int i=0;i<n;i++){
                rev[i]=(rev[i>>1]>>1)|((i&1)*(n>>1));
            }
            fft(a,1);
            for(int i=0;i<n;i++){
                a[i]=a[i]*a[i];
            }
            fft(a,-1);
            tot=ans=1LL*m*(m-1)*(m-2)/6;
            for(int i=1;i<n;i++){
                ll tmp=a[i].x+0.5;
                if(i%2==0){
                    tmp-=sum[i/2]-sum[i/2+1];
                }
                tmp>>=1;
                ans-=tmp*sum[i];
            }
            printf("%.7lf
    ",1.0*ans/tot);
        }
        return 0;
    }
  • 相关阅读:
    luogu P1073 最优贸易 |分层图最短路
    luogu P1901 发射站 |单调队列
    luogu P1759 通天之潜水 |背包
    luogu P1801 【黑匣子_NOI导刊2010提高(06)】|堆+分块
    bzoj1642[Usaco2007 Nov]Milking Time 挤奶时间*
    bzoj1616[Usaco2008 Mar]Cow Travelling游荡的奶牛*
    bzoj1623[Usaco2008 Open]Cow Cars 奶牛飞车*
    bzoj1612[Usaco2008 Jan]Cow Contest奶牛的比赛*
    bzoj1639[Usaco2007 Mar]Monthly Expense 月度开支*
    bzoj1601[Usaco2008 Oct]灌水*
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476878.html
Copyright © 2020-2023  润新知