• HDU 4609 3-idiots(FFT)


    题意:给出n个正整数(数组A)。每次随机选出三个数。问这三个数能组成三角形的概率为多大?

    首先,我们用类似桶排计数的方法作出两个数组a,b,储存每个长度有几条边,然后对两个数组求卷积。

    求出卷积后,这就代表了2条边能构成的边长度的集合了,注意,由于求卷积的时候可能把两条相同的边相加,所以最后求出的数组一定要减去这重复的部分,然后,先算x后算y等价于先算y后算x,所以要除以二。

    然后,对于第三条边a[i],我们这样考虑:令它作为这三条边中最大的那条!

    所以之前的卷积求出来的两边和一定会比这条边大,所以每次都计数:ans+=sum[mx]-sum[a[i]];

    然后减去重复部分:

        (1)一个选了i后面,一个选了i前面 (减去(i-1)*(n-i)个)

        (2)一个选了i,另一个随意 (减去n-1个)

        (3)两个都是i后面的 (减去C(n-i,2)个);

    非常interesting的题目!

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<complex>
     7 #define N 300005
     8 #define ll long long
     9 typedef std::complex<double> cd;
    10 int a[400005];
    11 ll C[400005],Sum[400005],A[400005],B[400005];
    12 int n,mxnum;
    13 int bitrev(int t,int n){
    14     int res=0;
    15     for (int i=0;i<n;i++) res|=((t>>(n-i-1))&1)<<i;//括号要多加 
    16     return res;
    17 }
    18 void fft(cd *a,int n,int rev){
    19     int len=1<<n;
    20     static cd y[N];double Pi=acos(-1);
    21     for (int i=0;i<len;i++) y[i]=a[bitrev(i,n)];
    22     for (int d=1;d<len;d<<=1){
    23         cd wn(exp(cd(0,Pi*rev/d)));
    24         for (int k=0;k<len;k+=2*d){
    25             cd w(1,0);
    26             for (int i=k;i<k+d;i++,w*=wn){
    27                 cd u=y[i],v=w*y[i+d];
    28                 y[i]=u+v;
    29                 y[i+d]=u-v;
    30             }
    31         }
    32     }
    33     if (rev==-1)
    34     for (int i=0;i<len;i++) y[i]/=len;
    35     for (int i=0;i<len;i++) a[i]=y[i];
    36 }
    37 void mul(ll *a,int la,ll *b,int lb,ll *c,int &lc){
    38     int len=1,n=0;
    39     static cd t1[N],t2[N];
    40     for (;len<la*2||len<lb*2;len<<=1,n++);
    41     for (int i=0;i<la;i++) t1[i]=cd(a[i],0);
    42     for (int i=0;i<lb;i++) t2[i]=cd(b[i],0);
    43     for (int i=la;i<len;i++) t1[i]=cd(0,0);
    44     for (int i=lb;i<len;i++) t2[i]=cd(0,0);
    45     fft(t1,n,1);fft(t2,n,1);
    46     for (int i=0;i<len;i++) t1[i]*=t2[i];
    47     fft(t1,n,-1);
    48     for (int i=0;i<len;i++) c[i]=(long long)(t1[i].real()+0.5);
    49     lc=len;
    50 }
    51 int main(){
    52     int T;
    53     scanf("%d",&T);
    54     while (T--){
    55         scanf("%d",&n);
    56         for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    57         mxnum=0;
    58         for (int i=1;i<=n;i++) mxnum=std::max(mxnum,a[i]);
    59         for (int i=1;i<=n;i++) A[a[i]]++,B[a[i]]++;
    60         int lc;
    61         mul(A,mxnum+1,B,mxnum+1,C,lc);
    62         for (int i=1;i<=n;i++) C[a[i]*2]--;
    63         for (int i=1;i<=mxnum*2;i++) C[i]/=2;
    64         Sum[0]=0;
    65         for (int i=1;i<=mxnum*2;i++) 
    66          Sum[i]=Sum[i-1]+C[i];
    67         std::sort(a+1,a+1+n);
    68         ll ans=0;
    69         for (int i=1;i<=n;i++){
    70             ans+=Sum[mxnum*2]-Sum[a[i]];
    71             ans-=(ll)n-1;
    72             ans-=(ll)(i-1)*(n-i);
    73             ans-=(ll)(n-i)*(n-i-1)/2;
    74         }
    75         ll sum=(ll)(n)*(n-1)*(n-2)/6;
    76         printf("%.7f
    ",(double)1.0*((double)(ans))/((double)sum));
    77         for (int i=0;i<=mxnum;i++) A[i]=B[i]=Sum[i]=C[i]=0;
    78     }
    79 }
  • 相关阅读:
    Java服务停止与开启
    跨域,php后端处理
    Mac 504 gateway timeout nginx
    Tp3.2 多数据库链接
    Redis 设置密码
    Redis 如何对外访问 lnmp安装
    tensorflow gpu安装
    ngx_http_upstream_check_module
    Nginx负载均衡+监控状态检测
    springboot+log4j2+slf4j控制台打印带sql日志
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5532460.html
Copyright © 2020-2023  润新知