HDU 4609 3-idiots FFT+容斥

时间:2023-11-29 21:35:26

一点吐槽:我看网上很多分析,都是在分析这个题的时候,讲了半天的FFT,其实我感觉更多的把FFT当工具用就好了

分析:这个题如果数据小,统计两个相加为 x 的个数这一步骤(这个步骤其实就是求卷积啊),完全可以母函数,无奈数据很大,就用FFT了

然后难点在于最后的统计,要减去自身,两个都大的,一大一小,包含自身,这是用到了容斥,再做相似的题的时候,应该多看看这方面

注:再次高度仰慕kuangbin神,这是我FFT的第二题,也是第二次用kuangbin FFT模板

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <map>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=4e5+;
const double pi = acos(-1.0);
struct complex{
double r,i;
complex(double R=,double I=){
r=R;i=I;
}
complex operator+(const complex &a)const{
return complex(r+a.r,i+a.i);
}
complex operator-(const complex &a)const{
return complex(r-a.r,i-a.i);
}
complex operator*(const complex &a)const{
return complex(r*a.r-i*a.i,r*a.i+i*a.r);
}
};
void change(complex x[],int len){
int i,j,k;
for(i=,j=len/;i<len-;++i){
if(i<j)swap(x[i],x[j]);
k=len/;
while(j>=k){j-=k;k>>=;}
if(j<k)j+=k;
}
}
void fft(complex x[],int len,int on){
change(x,len);
for(int i=;i<=len;i<<=){
complex wn(cos(-on**pi/i),sin(-on**pi/i));
for(int j=;j<len;j+=i){
complex w(,);
for(int k=j;k<j+i/;++k){
complex u = x[k];
complex t = w*x[k+i/];
x[k]=u+t;
x[k+i/]=u-t;
w=w*wn;
}
}
}
if(on==-)for(int i=;i<len;++i)x[i].r/=len;
}
complex x[N];
int a[N>>];
LL num[N],sum[N];
int main(){
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(num,,sizeof(num));
for(int i=;i<n;++i){scanf("%d",&a[i]);++num[a[i]];}
sort(a,a+n);
int len1 = a[n-] + ,len = ;
while(len<*len1)len<<=;
for(int i=;i<len1;++i)x[i]=complex(num[i],);
for(int i=len1;i<len;++i)x[i]=complex(,);
fft(x,len,);
for(int i=;i<len;++i)x[i]=x[i]*x[i];
fft(x,len,-);
for(int i=;i<len;++i)
num[i]=(long long)(x[i].r+0.5);
len=*a[n-];
for(int i=;i<n;++i)--num[a[i]+a[i]];
for(int i=;i<=len;++i)num[i]>>=;
for(int i=;i<=len;++i)sum[i]=sum[i-]+num[i];
LL cnt=;
for(int i=;i<n;++i){
cnt+=sum[len]-sum[a[i]];
cnt-=1ll*(n--i)*i;
cnt-=(n-);
cnt-=1ll*(n--i)*(n-i-)/;
}
LL tot=1ll*n*(n-)*(n-)/;
printf("%.7f\n",1.0*cnt/tot);
}
return ;
}