HDU-4609(FFT/NTT)

HDU-4609(FFT/NTT)

题意: 给出n个木棒,现从中不重复地选出3根来,求能拼出三角形的概率。

计算合法概率容易出现重复,所以建议计算不合法方案数

枚举选出的最大边是哪条,然后考虑剩下两条边之和小于等于它

两条边之和为\(x\)的方案数可以\(FFT/NTT\)得到,是一个简单的构造

\(f(x)=\sum x^{length_i}\),求出\(f(x)^2\),就能得到和的方案数,但是会重复,包括自己和自己算,一对算两次

处理一下前缀和即可

#include
using namespace std;

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)

template  inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } 
template  inline void cmax(T &a,T b){ ((a Cp;
Cp d[N];
ll a[N];

void FFT(int n,Cp *a,int f){
    rep(i,0,n-1) if(rev[i]>i) swap(a[i],a[rev[i]]);
    for(reg int i=1;i>1]>>1)|((i&1)<<(c-1));
        FFT(R,d,1);
        rep(i,0,R-1) d[i]=d[i]*d[i];
        FFT(R,d,-1);
        rep(i,0,R-1) a[i]=(ll)(d[i].real()/R+0.5);
        rep(i,1,n) a[b[i]*2]--;
        rep(i,1,R) a[i]/=2;    //处理重复情况
        rep(i,1,R) a[i]+=a[i-1];
        ll ans=0,sum=0;
        rep(i,1,n) {
            ans+=a[b[i]]; // 计算不合法方案数
            sum+=1ll*(i-1)*(i-2)/2;
        }
        rep(i,0,R+3) a[i]=0,d[i]=Cp(0,0);
        rep(i,0,ma+3) b[i]=0;
        ans=sum-ans;
        printf("%.7lf\n",1.0*ans/sum);
    }
}

你可能感兴趣的:(HDU-4609(FFT/NTT))