HDU 4609 3-idiots(FFT)

题意:给你n个木棍,让你求取三根木棍能组成三角形的概率,其实就是问你组成三角形的方法有多少种

思路:一点思路都没有,看了kuangbin聚聚的博客才理解了为什么要用FFT,以及之后的去重,写的很详细,但是这个题卡了内存,理解了以后用胡小兔爷的FFT,一直爆内存,主要是因为在求FFT的时候打复平面点,和他的倒数的那个位置,胡小兔爷是直接预处理打表的,QAQ,只好改成用的时候在进行计算的办法了

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 400040;
const double PI=acos(-1.0);
struct cp
{
    double r,i;
    cp(){}
    cp(double _r,double _i)
    {
        r=_r;i=_i;
    }
    cp operator +(const cp &a)const
    {
        return cp(a.r+r,a.i+i);
    }
    cp operator -(const cp &a)const
    {
        return cp(r-a.r,i-a.i);
    }
    cp operator *(const cp &a)const
    {
        return cp(r*a.r-i*a.i,r*a.i+i*a.r);
    }
    cp conj()
    {
        return cp(r,-i);
    }
};


void change(cp 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(cp y[],int len,int on)
{
    change(y,len);
//    for(int i=2;i<=len;i++){
//        printf("%d == %f
",i,y[i].r);
//    }
//    puts("");
    for(int h = 2;h <= len;h <<= 1)
    {
        cp wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
        for(int j = 0;j < len;j += h)
        {
            cp w(1,0);
            for(int k = j;k < j+h/2;k++)
            {
                cp u = y[k];
                cp 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 a[N/4];
long long num[N],sum[N];
cp x[N];
int main()
{
    int T,n,m;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            num[a[i]]++;
        }
        sort(a,a+n);
        m=a[n-1]+1;
        int as=1;
        while(as<2*m)as<<=1;
        for(int i=0;i<m;i++){
            x[i]=cp(num[i],0);
        }
        for(int i=m;i<as;i++){
            x[i]=cp(0,0);
        }
//        FFT_init();
        fft(x,as,1);
        for(int i=0;i<as;i++){
            x[i]=x[i]*x[i];
        }
        fft(x,as,-1);
        for(int i=0;i<as;i++){
            num[i]=(long long)(x[i].r+0.5);
        }
        as=2*a[n-1];
        for(int i=0;i<n;i++){
            num[a[i]+a[i]]--;
        }
        for(int i=1;i<=as;i++){
            num[i]/=2;
        }
        sum[0]=0;
        for(int i=1;i<=as;i++){
            sum[i]=sum[i-1]+num[i];
        }
        long long ans=0;
        for(int i=0;i<n;i++){
            ans+=sum[as]-sum[a[i]];
            ans-=(long long)(n-1-i)*i;
            ans-=(n-1);
            ans-=(long long)(n-1-i)*(n-i-2)/2;
        }
        long long tot=(long long)n*(n-1)*(n-2)/6;
        printf("%.7f
",(double)ans/tot);
    }
}


/*
2
4
1 3 3 4
4
2 3 3 4

*/
原文地址:https://www.cnblogs.com/lalalatianlalu/p/9416266.html