zoukankan      html  css  js  c++  java
  • [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);
        }
    }
    
  • 相关阅读:
    UVa 10118 记忆化搜索 Free Candies
    CodeForces 568B DP Symmetric and Transitive
    UVa 11695 树的直径 Flight Planning
    UVa 10934 DP Dropping water balloons
    CodeForces 543D 树形DP Road Improvement
    CodeForces 570E DP Pig and Palindromes
    HDU 5396 区间DP 数学 Expression
    HDU 5402 模拟 构造 Travelling Salesman Problem
    HDU 5399 数学 Too Simple
    CodeForces 567F DP Mausoleum
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8832835.html
Copyright © 2011-2022 走看看