[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;
}

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

原文地址:https://www.cnblogs.com/ShuraK/p/10106606.html