zoukankan      html  css  js  c++  java
  • hdu 4609 3-idiots(FFT+去重处理)

    3-idiots

    Problem Description

    King OMeGa catched three men who had been streaking in the street. Looking as idiots though, the three men insisted that it was a kind of performance art, and begged the king to free them. Out of hatred to the real idiots, the king wanted to check if they were lying. The three men were sent to the king's forest, and each of them was asked to pick a branch one after another. If the three branches they bring back can form a triangle, their math ability would save them. Otherwise, they would be sent into jail.
    However, the three men were exactly idiots, and what they would do is only to pick the branches randomly. Certainly, they couldn't pick the same branch - but the one with the same length as another is available. Given the lengths of all branches in the forest, determine the probability that they would be saved.
     
    Input
    An integer T(T≤100) will exist in the first line of input, indicating the number of test cases.
    Each test case begins with the number of branches N(3≤N≤105).
    The following line contains N integers a_i (1≤a_i≤105), which denotes the length of each branch, respectively.
     
    Output
    Output the probability that their branches can form a triangle, in accuracy of 7 decimal places.
     
    Sample Input
    2
    4
    1 3 3 4
    4
    2 3 3 4
    Sample Output
    0.5000000
    1.0000000
     
    题意给你n个木棍,问从中选出三根能组成一个三角形,那么有多少种选法?求出合法选法除以总选法的概率
    FFT可以处理选择任意两个木棍,这两个木棍的和的情况数,我们这里是算了好多重复的比如选了a[i]又选了a[i],我需要减一下
    再一想选x选y跟选y选x是一样的,我们再除以2,我们对两根木棍的和的情况求一个前缀和
    然后我们枚举a[i]作为三个木棍中最长的一个,我们先对答案笼统的加上剩下两根木棍和大于a[i]的情况数
    我们还要减去剩下两个木棍一根>=a[i]另一根<=a[i]的情况,再减去剩下两根木棍都>a[i]的情况,再减去剩下两根木棍中a[i]又被选了的情况
    统计一下就是答案了
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const double pi = acos(-1.0);
    const int maxn = 4e5+500;
    struct Complex
    {
        double r,i;
        Complex(double _r,double _i):r(_r),i(_i){}
        Complex(){}
        Complex operator +(const Complex &b)
        {
            return Complex(r+b.r,i+b.i);
        }
        Complex operator -(const Complex &b)
        {
            return Complex(r-b.r,i-b.i);
        }
        Complex operator *(const Complex &b)
        {
            return Complex(r*b.r-i*b.i,r*b.i+i*b.r);
        }
    };
    void change(Complex y[],int len)
    {
        int i,j,k;
        for(i = 1, j = len/2;i < len-1;i++)
        {
            if(i < j)swap(y[i],y[j]);
            k = len/2;
            while( j >= k)
            {
                j -= k;
                k /= 2;
            }
            if(j < k)j += k;
        }
    }
    void fft(Complex y[],int len,int on)
    {
        change(y,len);
        for(int h = 2;h <= len;h <<= 1)
        {
            Complex wn(cos(-on*2*pi/h),sin(-on*2*pi/h));
            for(int j = 0;j < len;j += h)
            {
                Complex w(1,0);
                for(int k = j;k < j+h/2;k++)
                {
                    Complex u = y[k];
                    Complex t = w*y[k+h/2];
                    y[k] = u+t;
                    y[k+h/2] = u-t;
                    w = w*wn;
                }
            }
        }
        if(on == -1)
            for(int i = 0;i < len;i++)
                y[i].r /= len;
    }
    int n;
    int a[maxn];
    ll num[maxn],sum[maxn];
    Complex A[maxn];
    int main()
    {
        //freopen("de.txt","r",stdin);
        int T;
        scanf("%d",&T);
        while (T--){
            memset(num,0,sizeof num);
            scanf("%d",&n);
            for (int i=0;i<n;++i) scanf("%d",&a[i]),num[a[i]]++;
            sort(a,a+n);
            int len=1;
            int len1=a[n-1]+1;
            while (len<2*len1) len<<=1;
            for (int i=0;i<len1;++i) 
                A[i]=Complex(num[i],0);
            for (int i=len1;i<len;++i)
                A[i]=Complex(0,0);
            fft(A,len,1);
            for (int i=0;i<len;++i)
                A[i]=A[i]*A[i];
            fft(A,len,-1);
            for (int i=0;i<len;++i) num[i]=(ll)(A[i].r+0.5);
            len = 2*a[n-1];
            for (int i=0;i<n;++i)
                num[a[i]+a[i]]--;
            for (int i=0;i<=len;++i)
                num[i]/=2;
            sum[0]=0;
            for (int i=1;i<=len;++i) sum[i]=sum[i-1]+num[i];
            ll ans = 0;
            for (int i=0;i<n;++i){
                ans+=sum[len]-sum[a[i]];
                ans-=(ll)(n-i-1)*i;
                ans-=n-1;
                ans-=(long long)(n-i-1)*(n-i-2)/2;
            }
            ll tot =(long long )(n-1)*n*(n-2)/6;
            printf("%.7f
    ",(double)ans/tot);
        }
        return 0;
    }
  • 相关阅读:
    Clean Code(三):注释
    Clean Code(二):函数
    mysql中查询某字段所在的表方法
    对于POI的XSSFCell 类型问题
    Clean Code 笔记 (一):命名
    java 注解
    搭建Eureka服务时报Cannot execute request on any known server 错误
    Jquery获取子父类方法
    Oracle 查询id相同多个数据取一条
    Ajax的使用及后台如何传参
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7327736.html
Copyright © 2011-2022 走看看