zoukankan      html  css  js  c++  java
  • [bzoj3513][MUTC2013]idiots_FFT

    idiots bzoj-3513 MUTC-2013

    题目大意:给定$n$根木棍,问随机选择三根能构成三角形的概率。

    注释:$1le nle 3cdot 10^5$,$1le a_ile 10^5$。


    想法

    考虑暴力:枚举三条边。复杂度$O(n^3)$。

    优化一下发现第三条边可以二分。复杂度$O(n^2logn)$。

    正解:

    设$g_i$表示选取两根长度为$i$的方案数。

    直接用$g$统计不合法情况即可。

    发现$g$可以用桶自卷积完成,而这个过程可以用$FFT$优化。

    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define N 100010 
    using namespace std; typedef double db;
    const db pi=acos(-1); typedef long long ll;
    inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
    int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
    struct cp
    {
    	db x,y;
    	cp() {x=y=0;}
    	cp(db x_,db y_) {x=x_,y=y_;}
    	cp operator + (const cp &a) const {return cp(x+a.x,y+a.y);}
    	cp operator - (const cp &a) const {return cp(x-a.x,y-a.y);}
    	cp operator * (const cp &a) const {return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
    }a[N<<2];
    int n,maxx,b[N];ll num[100005];
    void fft(cp *a,int len,int flg)
    {
    	int i,j,k,t;
    	cp w,wn,tmp;
    	for(i=k=0;i<len;i++)
    	{
    		if(i>k) swap(a[k],a[i]);
    		for(j=len>>1;(k^=j)<j;j>>=1);
    	}
    	for(k=2;k<=len;k<<=1)
    	{
    		wn=cp(cos(2*pi*flg/k),sin(2*pi*flg/k));
    		t=k>>1;
    		for(i=0;i<len;i+=k)
    		{
    			w=cp(1,0);
    			for(j=i;j<i+t;j++)
    			{
    				tmp=a[j+t]*w;
    				a[j+t]=a[j]-tmp;
    				a[j]=a[j]+tmp;
    				w=w*wn;
    			}
    		}
    	}
    	if(flg==-1) for(i=0;i<len;i++) a[i].x/=len;
    }
    int main()
    {
        int T,i,x;scanf("%d",&T);int len;
        while(T--)
        {
    		memset(num,0,sizeof num);
    		ll ans=0;
    		maxx=0;
    		memset(a,0,sizeof(a));
            n=rd(); for(i=1;i<=n;i++) x=rd(),b[i]=x,a[x].x++,maxx=max(x,maxx);
            len=1; while(len<(maxx<<1)) len<<=1;
            fft(a,len,1);
    		for(i=0;i<len;i++) a[i]=a[i]*a[i];
    		fft(a,len,-1);
            for(i=1;i<=n;i++) a[b[i]<<1].x--;
            for(i=1;i<=maxx;i++) num[i]=num[i-1]+(ll)(a[i].x/2+0.1);
            for(i=1;i<=n;i++) ans+=num[b[i]];
            printf("%.7f
    ",1-(1.0*ans/(1.0*n*(n-1)/6*(n-2))));
        }
    	return 0;
    }
    

    小结:从暴力入手其实并没有那么万能。比如这个题其实非常的考察思维。

  • 相关阅读:
    [转载]注解
    Spring可扩展的XML Schema机制 NamespaceHandlerSupport
    jvm中的年轻代 老年代 持久代 gc ----------转载
    反射原理
    舍入误差
    mysql突然宕机后事务如何处理?
    redis为什么设计成单线程并且还这么快?
    mysql架构学习
    用户级线程和内核级线程的区别
    G1垃圾收集器
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10106606.html
Copyright © 2011-2022 走看看