• 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
    */
  • 相关阅读:
    星球居民突破 1800 人!
    测试数据管理
    解决InnoDB: Table mysql/innodb_index_stats has length mismatch in the column name table_name. Please run mysql_upgrade
    Warning: file_get_contents(): open_basedir restriction in effect. File(/proc/uptime) is not within the allowed path(s)解决方法
    Java终止线程的三种方式
    线程中断interrupt
    Linux 开启防火墙 避免非干系人误操作的处理
    Oracle12c 快速启动命令设置
    Docker 运行 Redis Rabbitmq seata-server ftp 的简单办法
    mysql8 CentOS7 简要安装说明
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10159458.html
Copyright © 2020-2023  润新知