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;
    }
  • 相关阅读:
    android ListView几个比较特别的属性
    一.反编译Apk得到Java源代码
    android 正确获取屏幕像素大小
    android 动态添加控件
    动态加控件
    android ListView的美化涉及到的一些属性
    ASP.NET中的状态管理(转载)
    ASP.NET 2.0使用user profile储存信息前,如何部署aspnetdb.mdf和连接
    ASP.NET中防止Access数据库下载
    个性化用户配置概述、Profile配置节详细介绍
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7327736.html
Copyright © 2011-2022 走看看