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

    题意:

    给出n条边,问选择3个边能构成三角形的概率

    题解:

    边权不大

    考虑FFT的组合意义,得到的f[i]的值,是所有的j+k=i的a[j]*b[k]

    如果把下标当做边权的话,FFT一次,就得到了选择两个边,能组成i的方案数。

    三角形充要条件,最小的两个边之和大于最大边。

    但是最大边可能之前在较小的用过了。

    所以,考虑不合法的情况,最大边c>=a+b

    这样,c一定就是一个>=a+b的后缀和了。

    C(n,3)减去不合法的即可。

    对于任意一个合法的,一定没有被减去,任意一个不合法的一定减去了。

    正确。

    注意:

    1.多组数据清空,,用到的多项式是m>2*mx,buc的上界是mx

    2.buc*buc可能爆int

    3.FFT注意精度误差,绝对值可能在(0~0.5)之间,不能直接取整,采用四舍五入

    a=floor(b+0.5)或者,a=round(b)

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=1e5+5;
    const double Pi=acos(-1);
    ll n;
    ll buc[4*N],sum[4*N];
    struct node{
        double x,y;
        node(){}
        node(double xx,double yy){
            x=xx;y=yy;
        }
        node friend operator *(node a,node b){
            return node(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
        }
        node friend operator +(node a,node b){
            return node(a.x+b.x,a.y+b.y);
        }
        node friend operator -(node a,node b){
            return node(a.x-b.x,a.y-b.y);
        }
        void clear(){
            x=0.0,y=0.0;
        }
    }a[4*N],b[4*N],c[4*N];
    
    int rev[4*N];
    void fft(node *f,int n,int c){
        for(reg i=0;i<n;++i){
            if(i<rev[i]) swap(f[i],f[rev[i]]);
        }
        for(reg p=2;p<=n;p<<=1){
            int len=p/2;
            node gen=node(cos(Pi/len),c*sin(Pi/len));
            for(reg l=0;l<n;l+=p){
                node buf=node(1,0);
                for(reg k=l;k<l+len;++k){
                    node tmp=buf*f[k+len];
                    f[k+len]=f[k]-tmp;
                    f[k]=f[k]+tmp;
                    buf=buf*gen;
                }
            }
        }
    }
    ll mx;
    int m;
    void clear(){
        
        for(reg i=0;i<m;++i) a[i].clear(),b[i].clear(),c[i].clear();
        for(reg i=0;i<=mx;++i) buc[i]=0;mx=0;
    }
    int main(){
        int T;
        rd(T);
        while(T--){
            scanf("%lld",&n);
            clear();
            int x;
    //        for(reg i=0;i<16;++i){
    //            cout<<buc[i]<<" ";
    //        }cout<<endl;
            for(reg i=1;i<=n;++i){
                rd(x);mx=max(mx,(ll)x);
                buc[x]++;
            }
            m=1;
            for(;m<=mx*2;m<<=1);
            for(reg i=0;i<m;++i){
                rev[i]=(rev[i>>1]>>1)|((i&1)?(m>>1):0);
                a[i].x=buc[i];
                b[i].x=buc[i];
            }
            //cout<<" mx "<<mx<<" "<<m<<endl;
            //cout<<" buc "<<endl;
    //        for(reg i=0;i<m;++i){
    //            cout<<buc[i]<<" ";
    //        }cout<<endl;
            fft(a,m,1);fft(b,m,1);
            for(reg i=0;i<m;++i) b[i]=a[i]*b[i];
            fft(b,m,-1);
            //cout<<" dughrg "<<endl;
            for(reg i=0;i<m;++i) b[i].x=round(b[i].x/m);
            sum[mx]=buc[mx];
            for(reg i=mx-1;i>=0;--i) sum[i]=sum[i+1]+buc[i];
            double tot=n*(n-1)*(n-2)/6;
            double ans=tot;
            for(reg i=1;i<=mx;++i){
                //cout<<" ii "<<i<<" "<<b[i].x<<endl;
                ll tmp=0;
                if(i%2==0){
                    tmp=buc[i/2];
                }
                b[i].x-=tmp*tmp;
                b[i].x/=2;
                b[i].x+=tmp*(tmp-1)/2;
                //cout<<" b[i] "<<b[i].x<<endl;
                ans-=b[i].x*sum[i];    
            }
            printf("%.7lf
    ",ans/tot);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/21 21:03:28
    */
  • 相关阅读:
    LeetCode Best Time to Buy and Sell Stock
    LeetCode Scramble String
    LeetCode Search in Rotated Sorted Array II
    LeetCode Gas Station
    LeetCode Insertion Sort List
    LeetCode Maximal Rectangle
    Oracle procedure
    浏览器下载代码
    Shell check IP
    KVM- 存储池配置
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10159458.html
Copyright © 2011-2022 走看看