hdu 4609 3-idiots

来源:互联网 发布:java火车票系统代码 编辑:程序博客网 时间:2024/06/05 04:48

三个数若能组成三角形,其实只需要满足:将三个数升序排列成abc,那么a+b>c。试着构造一个数列中所有满足a+b>x的二元组(a,b),发现除了a<xb<x的,其他二元组都非常好构造。
Ai表示数列中满足a+b=i的二元组的数量,ai表示数列中i的个数,则Ai=jij=0ajaij,其实就是a自己做一次卷积而已。用fft求出卷积之后,对于每一个值x,设小于x的数的数量为c,大于等于x的数的数量为dAs=jMAXj=sAj,那么以x为最长边的三角形个数就为ai(AscdC2d)+cC2ai+C3ai。处理A的后缀和及a的前缀和之后,扫一遍累加答案即可。

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<vector>#include<cmath>#include<queue>using namespace std;typedef long long ll;#define clr(a) memset(a,0,sizeof(a))const double PI=acos(-1.0);struct cx{    double a,b;    cx(){};cx(double x,double y):a(x),b(y){};    friend cx operator+(const cx&,const cx&);    friend cx operator-(const cx&,const cx&);    friend cx operator*(const cx&,const cx&);}ar[1<<18],sr[1<<18];cx operator+(const cx&a,const cx&b){return cx(a.a+b.a,a.b+b.b);};cx operator-(const cx&a,const cx&b){return cx(a.a-b.a,a.b-b.b);};cx operator*(const cx&a,const cx&b){return cx(a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a);};cx cp(cx a){double t=a.a*a.a+a.b*a.b;return cx(a.a/t,-a.b/t);};void fft(int n,cx*tr,bool fg){    if(n>1){        int i,j,t;cx w(cos(2.0*PI/(double)n),sin(2.0*PI/(double)n)),x(1.0,0);if(fg)w=cp(w);        for(i=j=0;j<n;j+=2,++i)sr[i]=tr[j];        for(j=1;j<n;j+=2,++i)sr[i]=tr[j];        for(i=0;i<n;++i)tr[i]=sr[i];        fft(n>>1,tr,fg),fft(n>>1,tr+(n>>1),fg);        for(i=0,j=n>>1;i<j;++i,x=x*w)sr[i]=tr[i]+x*tr[i+j],sr[i+j]=tr[i]-x*tr[i+j];        for(i=0;i<n;++i)tr[i]=sr[i];    }};int n,lr[100010];ll qm[1<<18],cb[100010][4];void _cl(){    int i,j;    for(clr(cb),cb[0][0]=1,i=1;i<=100000;++i)for(cb[i][0]=1,j=1;j<=3;++j)        cb[i][j]=cb[i-1][j-1]+cb[i-1][j];};void cl(){    int i,j,t,a,b,d,sn;ll r;scanf("%d",&n);    for(clr(lr),sn=i=0;i<n;++i){        scanf("%d",&a);sn=max(sn,a);lr[a]++;    }    for(d=sn++,t=1;t<sn;t<<=1);t<<=1;    for(i=0;i<sn;++i)ar[i]=cx((double)lr[i],0.0);    for(;i<t;++i)ar[i]=cx(0.0,0.0);fft(sn=t,ar,0);    for(i=0;i<sn;++i)ar[i]=ar[i]*ar[i];fft(sn,ar,1);    for(clr(qm),i=0;i<sn;++i)qm[i]=ar[i].a/(double)sn+0.5;    for(i=2;i<sn&&(i/2<=d);i+=2)qm[i]-=lr[i/2];    for(i=0;i<sn;++i)qm[i]/=2;    for(i=1;i<=d;++i)lr[i]+=lr[i-1];    for(i=sn-2;i>=0;--i)qm[i]+=qm[i+1];    for(r=0,i=1;i<=d;++i){        t=lr[i]-lr[i-1];if(!t)continue;        a=lr[i-1],b=lr[d]-lr[i-1];        r+=(ll)t*(qm[i+1]-(ll)b*a-cb[b][2]);        r+=cb[t][2]*a+cb[t][3];    }    printf("%.7lf\n",(double)r/(double)cb[n][3]);};int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);    freopen("out.txt","w",stdout);#endif    int t;for(_cl(),scanf("%d",&t);t;--t)cl();    return 0;};
0 0
原创粉丝点击