• HDU4609:3-idiots(FFT)


    Description

    Input

    Output

    Sample Input

    Sample Output

    Solution

    题意:给你$n$根木棍,问你任选三根能构成三角形的概率是多少。

    写挂sb细节心态崩了

    首先把读入的长度$a$数组开个桶$c$存下来,然后卷积一下$c$数组。可以发现卷完后的数组$c$就是“任选两根木棍(可以重复选)长度和为$c[i]$的方案数。”

    因为有可能自己和自己算到一起,所以$c[a[i]*2]--$。因为$i+j$,$j+i$是一种,所以要$c[i]=c[i]/2$。

    对$c$数组做一下前缀和,记为$sumd$。然后$sort$一下$a$数组,从小到大枚举,统计当$a[i]$为三角形最长边时的方案数,则另外两边之和$>a[i]$。$ans+=sumd[MAX*2]-sumd[a[i]]$

    同时这些方案里面还有一些不合法的方案。

    另外两条边两条均$>ai$,$ans-=(n-i)*(n-i-1)/2$

    另外两条边一条$>ai$,一条$<ai$,$ans-=(n-i)*(i-1)$

    另外两条边一条$=ai$,另一条随意,$ans-=n-1$

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define N (400009)
     7 #define LL long long
     8 using namespace std;
     9 
    10 LL T,n,ans,a[N],fn,l,r[N],d[N],sumd[N],MAX;
    11 
    12 double pi=acos(-1.0);
    13 struct complex
    14 {
    15     double x,y;
    16     complex (double xx=0,double yy=0)
    17     {
    18         x=xx; y=yy;
    19     }
    20 }c[N];
    21 
    22 complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
    23 complex operator - (complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
    24 complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
    25 complex operator / (complex a,double b){return complex(a.x/b,a.y/b);}
    26 
    27 void FFT(int n,complex *a,int opt)
    28 {
    29     for (int i=0; i<n; ++i)
    30         if (i<r[i])
    31             swap(a[i],a[r[i]]);
    32     for (int k=1; k<n; k<<=1)
    33     {
    34         complex wn=complex(cos(pi/k),opt*sin(pi/k));
    35         for (int i=0; i<n; i+=(k<<1))
    36         {
    37             complex w=complex(1,0);
    38             for (int j=0; j<k; ++j,w=w*wn)
    39             {
    40                 complex x=a[i+j], y=w*a[i+j+k];
    41                 a[i+j]=x+y; a[i+j+k]=x-y;
    42             }
    43         }
    44     }
    45     if (opt==-1) for (int i=0; i<n; ++i) a[i]=a[i]/n;
    46 }
    47 
    48 int main()
    49 {
    50     scanf("%lld",&T);
    51     while (T--)
    52     {
    53         memset(c,0,sizeof(c));
    54         memset(r,0,sizeof(r));
    55         l=0; ans=0; MAX=0;
    56         scanf("%lld",&n);
    57         for (int i=1; i<=n; ++i)
    58         {
    59             scanf("%lld",&a[i]);
    60             c[a[i]].x++;
    61         }
    62         sort(a+1,a+n+1); MAX=a[n];
    63         fn=1;
    64         while (fn<=MAX*2) fn<<=1, l++;
    65         for (int i=0; i<fn; ++i)
    66             r[i]=(r[i>>1]>>1) | ((i&1)<<(l-1));
    67         FFT(fn,c,1);
    68         for (int i=0; i<fn; ++i)
    69             c[i]=c[i]*c[i];
    70         FFT(fn,c,-1);
    71         for (int i=1; i<fn; ++i)
    72             d[i]=((LL)(c[i].x+0.5));//一开始括号里写成int了…… 
    73         for (int i=1; i<=n; ++i)
    74             d[a[i]*2]--;
    75         for (int i=1; i<=MAX*2; ++i)
    76             d[i]>>=1, sumd[i]=sumd[i-1]+d[i];
    77         for (int i=1; i<=n; ++i)
    78         {
    79             ans+=sumd[MAX*2]-sumd[a[i]];
    80             ans-=(n-i)*(n-i-1)/2;//两条都大于a[i]
    81             ans-=(n-i)*(i-1);//一条大于,一条小于 
    82             ans-=n-1;//一条等于,一条随意 
    83         }
    84         printf("%.7lf
    ",1.0*ans/(n*(n-1)*(n-2)/6));
    85     }
    86 }
  • 相关阅读:
    《网络》:关于计算机网络的必备常识【无序】(不定时更新)
    《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet
    《网络》:交换机基本配置命令
    启动eclipse时出现“Failed to load the JNI shared library jvm.dll”错误及解决
    java之servlet小记
    Nokia大事录
    Android之HandlerThread
    Android进程间的通信之AIDL
    Android进程间的通信之Messenger
    Loaders
  • 原文地址:https://www.cnblogs.com/refun/p/10094652.html
Copyright © 2020-2023  润新知