• [MUTC2013][bzoj3513] idiots [FFT]


    题面

    传送门

    思路

    首先有一个容斥原理的结论:可以组成三角形的三元组数量=所有三元组-不能组成三角形的三元组

    也就是说我们只要求出所有不能组成三角形的三元组即可

    我们考虑三元组(a,b,c),a<=b<=c,其不能组成三元组的条件是a+b<=c

    然后,这道题中并没有顺序限制

    于是我们考虑用sum[i]表示长度为i的木棍的个数

    将sum[i]为$x^i$的系数的多项式自乘,得到一个2*n项的多项式

    那么新多项式(设为S)的第i项系数S[i]就代表着选择总和为i的两条边的方法数量

    注意这个S[i]并不就是最后的答案,因为如果i是偶数,那么原来长度为i/2的边会被算两遍,所以要减去sum[i/2]

    同时,这样处理以后的所有S[i]还要除二,因为会出现(i,j)(j,i)重复计算的情况

    最后,我们维护sum的后缀和suf,答案就是$sum_{i=1}{maxlen}S[i]suf[i]$了

    不要忘记用所有三元组的数量减掉这个答案

    Code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    using namespace std;
    inline int read(){
        int re=0,flag=1;char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-') flag=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
        return re*flag;
    }
    struct complex{
        double x,y;
        complex(double xx=0,double yy=0){x=xx;y=yy;}
        complex operator +(const complex &b){return complex(b.x+x,b.y+y);}
        complex operator -(const complex &b){return complex(-b.x+x,-b.y+y);}
        complex operator *(const complex &b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
    }A[600010];
    const double pi=acos(-1.0);
    int n,sum[300010],limit=1,cnt=0,m,suf[300010],r[600010],maxn; 
    void fft(complex *a,double type){
        int i,mid,j,k,R;complex w,wn,x,y;
        for(i=0;i<limit;i++) if(i<r[i]) swap(a[i],a[r[i]]);
        for(mid=1;mid<limit;mid<<=1){
            wn=complex(cos(pi/mid),type*sin(pi/mid));
            for(R=mid<<1,j=0;j<limit;j+=R){
                w=complex(1,0);
                for(k=0;k<mid;k++,w=w*wn){
                    x=a[j+k];y=w*a[j+k+mid];
                    a[j+k]=x+y;
                    a[j+k+mid]=x-y;
                }
            }
        }
    }
    ll f[300010];
    int main(){
        int T=read(),i,t1;ll ans,tot;
        while(T--){
            memset(suf,0,sizeof(suf));memset(sum,0,sizeof(sum));
            n=read();m=0;limit=1;cnt=0;memset(r,0,sizeof(r));
            memset(A,0,sizeof(A));ans=tot=(ll)n*(ll)(n-1)*(ll)(n-2)/6ll;
             
            for(i=1;i<=n;i++) t1=read(),sum[t1]++,A[t1].x++,m=max(m,t1);
            for(i=m;i>=1;i--) suf[i]=suf[i+1]+sum[i];
             
            maxn=m<<1;
            while(limit<=maxn) limit<<=1,cnt++;
            for(i=0;i<limit;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(cnt-1)));
             
            fft(A,1);
            for(i=0;i<=limit;i++) A[i]=A[i]*A[i];
            fft(A,-1);
             
            for(i=0;i<=limit;i++){
                f[i]=(ll)(A[i].x/limit+0.5);
                if(!(i&1)) f[i]-=(ll)(sum[i>>1]);
                f[i]>>=1;
    
            }
             
            for(i=0;i<=limit;i++) ans-=f[i]*(ll)suf[i];
            printf("%.7lf
    ",(double)ans/(double)tot);
        }
    }
    
  • 相关阅读:
    C语言数据类型大学霸IT达人
    无线攻击工具MDK3常用命令大学霸IT达人
    WPS漏洞利用工具Bully常见命令集合
    无线密码离线破解工具Pyrit常用命令集合大学霸IT达人
    Wifite工具常用命令集合大学霸IT达人
    Linux防火墙命令大全
    详解nginx的rewrite应用,Nginx高级之Rewrite规则
    Nginx常用屏蔽规则,让你的网站更安全
    Nginx与安全有关的几个配置
    systemd 和 systemctl 使用深入理解
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8832835.html
Copyright © 2020-2023  润新知