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;
    }
  • 相关阅读:
    jvm 虚拟机参数_新生代内存分配
    jvm 虚拟机参数_堆内存分配
    Xshell 安装 Xftp
    使用 Xshell 连接 linux 系统
    linux 常用命令
    java JSON 和 Object 相互转换
    vsftp实现只能上传不能下载、删除权限配置
    从返回的HTTP Header信息中隐藏Apache的版本号及PHP的X-Powered-By信息
    在SecureCRT中无需输入密码登录Linux主机
    ssh 设置私钥实现两台linux主机无密码访问
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7327736.html
Copyright © 2011-2022 走看看