• 【BZOJ3513】[MUTC2013]idiots FFT


    【BZOJ3515】[MUTC2013]idiots

    Description

    给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率。

    Input

    第一行T(T<=100),表示数据组数。
    接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个数表示a_i。
    3≤N≤10^5,1≤a_i≤10^5

    Output

    T行,每行一个整数,四舍五入保留7位小数。

    Sample Input

    2
    4
    1 3 3 4
    4
    2 3 3 4

    Sample Output

    0.5000000
    1.0000000

    HINT

    T<=20

    N<=100000

    题解:我们依旧采用补集法,如果我们求出任意s[i]表示选两个木棍使得长度和为i的方案数,那么可以枚举最长边,统计∑s[a[i]]即可。

    那么如何求出s数组呢?FFT。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #define pi acos(-1.0)
    using namespace std;
    typedef long long ll;
    struct cp
    {
    	double x,y;
    	cp () {}
    	cp (double a,double b){x=a,y=b;}
    	cp operator + (cp a) {return cp(x+a.x,y+a.y);}
    	cp operator - (cp a) {return cp(x-a.x,y-a.y);}
    	cp operator * (cp a) {return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
    }l1[1<<20],l2[1<<20];
    int n,m,len;
    int v[1<<20];
    ll ans,sum;
    ll s[1<<20];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void FFT(cp *a,int f)
    {
    	int i,j,k,h;
    	cp t;
    	for(i=k=0;i<len;i++)
    	{
    		if(i>k)	swap(a[i],a[k]);
    		for(j=(len>>1);(k^=j)<j;j>>=1);
    	}
    	for(h=2;h<=len;h<<=1)
    	{
    		cp wn(cos(2*pi*f/h),sin(2*pi*f/h));
    		for(j=0;j<len;j+=h)
    		{
    			cp w(1,0);
    			for(k=j;k<j+h/2;k++)	t=w*a[k+h/2],a[k+h/2]=a[k]-t,a[k]=a[k]+t,w=w*wn;
    		}
    	}
    }
    void calc(cp *a)
    {
    	FFT(a,1);
    	for(int i=0;i<len;i++)	a[i]=a[i]*a[i];
    	FFT(a,-1);
    	for(int i=0;i<len;i++)	s[i]+=ll(a[i].x/len+0.1);
    }
    void work()
    {
    	n=rd(),m=0;
    	int i;
    	for(i=1;i<=n;i++)	v[i]=rd(),m=max(m,v[i]<<1);
    	for(len=1;len<=m+1;len<<=1);
    	for(i=0;i<len;i++)	l1[i]=cp(0,0);
    	memset(s,0,sizeof(s));
    	for(i=1;i<=n;i++)	l1[v[i]].x+=1,s[v[i]<<1]--;
    	calc(l1);
    	for(i=1;i<=m;i++)	s[i]+=s[i-1];
    	ans=(ll)n*(n-1)*(n-2)/6,sum=0;
    	for(i=1;i<=n;i++)	sum+=s[v[i]];
    	printf("%.7lf
    ",(1-0.5*sum/ans));
    }
    int main()
    {
    	int T=rd();
    	while(T--)	work();
    	return 0;
    }//2 4 1 3 3 4 4 2 3 3 4
  • 相关阅读:
    打卡规则小模块设计
    json和ajax学习
    求两个数的百分比&时间格式化&ajax返回json
    spring security运行流程图(转)
    DelegatingFilterProxy作用浅析
    网站URL重写(Java UrlRewrite 的使用)
    JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
    JQuery 的Ajax的使用
    servlet程序HTTP Status 500
    CanvasRenderingContext2D.drawImage()无效,not working
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7367607.html
Copyright © 2020-2023  润新知