HDU 4609 3-idiots

传送门

问给定n条小木棍 随机选3根构成三角形的概率

看起来和多项式没啥关系对不对 = =

但实际上它的确可以用多项式来做qaq

我们构造多项式f(x)=sum x^{a_i}

然后自乘一下就能得到两根木棍拼起来的方案数

然后枚举所有拼出来的长度 算一下>=这个长度的木棍个数

求出不能拼成三角形的方案数

然后最后用C(3,n)减一减 除一除就可以了qwq

【注意sum的预处理范围是两倍权值T^T】

附代码。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define inf 20021225
#define db double
#define mxn 400010
using namespace std;

const db pi=acos(-1.0);

struct complex
{
    db x,y;
    complex(){}
    complex(db _x,db _y){x=_x,y=_y;}
}f[mxn],g[mxn];

complex operator +(complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
complex operator -(complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
complex operator *(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);}
int rev[mxn];
int init(int n)
{
    int lim=1,l=0;
    while(lim<n)    lim<<=1,l++;
    for(int i=1;i<lim;i++)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    return lim;
}

void fft(complex *a,int n,int f)
{
    for(int i=1;i<n;i++)    if(rev[i]>i)
        swap(a[rev[i]],a[i]);
    for(int k=2;k<=n;k<<=1)
    {
        int mid = k>>1; complex Wn=complex(cos(pi/mid),f*sin(pi/mid));
        for(int i=0;i<n;i+=k)
        {
            complex w=complex(1.0,0.0);
            for(int j=0;j<mid;j++,w=w*Wn)
            {
                complex x=a[i+j],y=w*a[i+mid+j];
                a[i+j] = x+y; a[i+mid+j]= x-y;
            }
        }
    }
    if(f==-1)   for(int i=0;i<n;i++)    a[i].x=(a[i].x+0.5)/(db)n;
}
int n,a[mxn],sum[mxn];
ll ans;
void work()
{
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)   f[a[i]].x++,g[a[i]*2].x++;
    //for(int i=0;i<=20;i++)    printf("%f %f
",f[i].x,f[i].y);
    int lim=init(200000);
    fft(f,lim,1);
    for(int i=0;i<lim;i++)  f[i]=f[i]*f[i];
    fft(f,lim,-1);
    for(int i=1;i<lim;i++)
    {
        //if(i<10)  printf("%d %.2f
",i,f[i].x);
        f[i].x-=g[i].x;
        ll tmp=f[i].x/2.0;
        ans+=(ll)tmp*(n-sum[i-1]);
        //if(tmp)	printf("%lld %d
",tmp,n-sum[i-1]);
        //if(i<10)  printf("%d %I64d %d
",i,tmp,calc(i)-2);
    }
    //printf("%lld
",ans);
    ans=(ll)n*(n-1ll)*(n-2ll)/6ll -ans;
    ll tot=(ll)n*(n-1ll)*(n-2ll)/6ll;
    printf("%.7lf
",(db)ans/tot);
}

void clear()
{
    memset(sum,0,sizeof(sum));
    for(int i=0;i<mxn;i++)  f[i]=complex(0,0),g[i]=complex(0,0);
    n=ans=0;
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        clear();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)   scanf("%d",&a[i]),sum[a[i]]++;
        for(int i=1;i<=200000;i++)  sum[i]+=sum[i-1];
        work();
    }
    return 0;
}
/**
1
4
100000 100000 100000 100000
*/
原文地址:https://www.cnblogs.com/hanyuweining/p/10321900.html