题外话:好久没写blog了啊~~

题目传送门

题目大意:给你m条长度为ai的线段,求在其中任选三条出来,能构成三角形的概率。即求在这n条线段中找出三条线段所能拼出的三角形数量除以$\binom{m}{3}$。

假设我们手中有3条长度分别为$x,y,z$的边(为了简化问题我们假设$x<y<z$,$x,y,z$相等的情况另行讨论),如果他们能拼成三角形,必然满足$x+y>z$且$z-y<x$。

该题的$O(m^3)$做法:枚举其中的3条边,套用上面的判断公式,进行累计。

但通过简单的变式,我们假设我们已经确定了$x$和$y$,那么$z$的范围即为$[y,x+y)$,我们维护一个数组$num$,$num_i$表示长度为i的线段数量。再维护一个num的前缀和sum。则$ans=\sum^{n-1}_{x=1}  \sum^{n}_{y=x+1} num_x * num_y*(sum[x+y-1]-sum[y])$,运算该和式的时间复杂度为$O(n^2)$,此处的n表示最长线段的长度。

然而还是会TLE。。。。

我们考虑对其做一些变式。

$ans=\sum^{n-1}_{x=1}  \sum^{n}_{y=x+1} num_x * num_y*(sum[x+y-1]-sum[y])$

$=\sum^{n-1}_{x=1}  \sum^{n}_{y=x+1} num_x * num_y*sum[x+y-1] -\sum^{n-1}_{x=1}  \sum^{n}_{y=x+1} num_x * num_y*sum[y]$

该式子的后半部分,我们可以通过维护$num_y*sum[y]$的后缀和,实现O(n)的计算。

下面我们继续对式子的前半部分变式。令t=x+y。则有

$=\frac{1}{2}\sum^{2n}_{t=2}  \sum^{t-1}_{p=1} num_p*num_{t-p}*sum[t-1] -\frac{1}{2}\sum^{n}_{i=1}num_i^2*sum[2*i-1]$

我们发现,该式子的$\sum_{p=1}^{t-1} num_{p}\times num_{t-p}$,可以用FFT求出。则时间复杂度成功降低至O(n log n),而式子的后半部分可以O(n)求出,求和时间复杂度降低至O(n log n)。

下面说下x=y=z,x=y<z,x<y=z的处理方法。

x=y=z:$\sum _{\forall num_x>2} \binom{num_x}{3}$

x=y<z: $\sum _{x=1}^{n} \binom{num_x}{2}*(sum[2x-1]-sum[x])$

x<y=z:$\sum_{x=1}^{n}(sumc2_n-sumc2_x)$ ,其中$sumc2_x$ 表示$\sum_{i=1}^{x}\binom{num_x}{2}$。

把这三种情况和最初描述的情况相加即可。

 #include<bits/stdc++.h>
#define M 270000
#define cp complex<double>
#define PI acos(-1)
#define L long long
using namespace std;
cp a[M];
void change(cp a[],int len){
for(int i=,j=;i<len-;i++){
if(i<j) swap(a[i],a[j]);
int k=len>>;
while(j>=k) j-=k,k>>=;
j+=k;
}
}
void fft(cp a[],int n,int on){
change(a,n); cp t,u;
for(int h=;h<=n;h<<=){
cp wn(cos(-on**PI/h),sin(-on**PI/h));
for(int j=;j<n;j+=h){
cp w(,);
for(int k=j;k<j+(h>>);k++){
u=a[k]; t=w*a[k+(h>>)];
a[k]=u+t; a[k+(h>>)]=u-t;
w=w*wn;
}
}
}
}
L num[M]={},sum[M]={},sumhh[M]={},sumc2[M]={},sc[M]={},ans=; int Main(){
int m,n,maxn=; scanf("%d",&n);
for(int i=;i<=n;i++){
int x; scanf("%d",&x);
num[x]++; maxn=max(maxn,x);
}
for(m=;m<(maxn*+);m<<=);
for(int i=;i<m;i++) a[i]=cp(num[i],);
fft(a,m,);
for(int i=;i<m;i++) a[i]=a[i]*a[i];
fft(a,m,-);
for(int i=;i<m;i++) sc[i]=(a[i+].real()+0.5)/m;
for(int i=;i<m;i++){
sum[i]=sum[i-]+num[i];
sumc2[i]=sumc2[i-]+num[i]*(num[i]-)/;
} L ans1=,ans2=,ans3=,ans4=;
for(int i=;i<=maxn;i++) if(num[i]>)
ans1+=(L)num[i]*(num[i]-)*(num[i]-);
ans1/=;//x=y=z
for(int i=;i<=maxn;i++)
ans2+=(L)num[i]*(num[i]-)*(sum[*i-]-sum[i]);
ans2/=;//x=y<z
for(int i=;i<=maxn;i++)
ans3+=num[i]*(sumc2[maxn]-sumc2[i]);
//x<y=z
for(int i=;i<*maxn;i++) ans4+=sum[i]*sc[i];
for(int i=;i<=maxn;i++) ans4-=num[i]*num[i]*sum[*i-];
ans4/=;//x<y<z卷积部分 for(int i=maxn;i;i--) sumhh[i]=sumhh[i+]+num[i]*sum[i];
for(int i=;i<maxn;i++) ans4-=num[i]*sumhh[i+];
ans=ans1+ans2+ans3+ans4; double fenmu=(L)n*(n-)*(n-)/;
double hh=ans/fenmu;
printf("%.7lf\n",hh);
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int cas; scanf("%d",&cas);
while(cas--){
memset(num,,sizeof(num)); memset(sum,,sizeof(sum));
memset(sumhh,,sizeof(sumhh)); memset(sumc2,,sizeof(sumc2));
memset(sc,,sizeof(sc)); memset(a,,sizeof(a)); ans=;
Main();
}
}

【hdu4609】 3-idiots FFT的更多相关文章

  1. 【bzoj3513】[MUTC2013]idiots FFT

    题目描述 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. 输入 第一行T(T<=100),表示数据组数. 接下来若干行描述T组数据,每组数据第一行是n,接下来一行有n个 ...

  2. 【BZOJ3160】万径人踪灭(FFT,Manacher)

    [BZOJ3160]万径人踪灭(FFT,Manacher) 题面 BZOJ 题解 很容易想到就是满足条件的子序列个数减去回文子串的个数吧... 至于满足条件的子序列 我们可以依次枚举对称轴 如果知道关 ...

  3. 【BZOJ3527】力(FFT)

    [BZOJ3527]力(FFT) 题面 Description 给出n个数qi,给出Fj的定义如下: \[Fj=\sum_{i<j}\frac{q_i q_j}{(i-j)^2 }-\sum_{ ...

  4. 【BZOJ4827】【HNOI2017】礼物(FFT)

    [BZOJ4827][HNOI2017]礼物(FFT) 题面 Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每 ...

  5. 【Matlab】快速傅里叶变换/ FFT/ fftshift/ fftshift(fft(fftshift(s)))

    [自我理解] fft:可以指定点数的快速傅里叶变换 fftshift:将零频点移到频谱的中间 用法: Y=fftshift(X) Y=fftshift(X,dim) 描述:fftshift移动零频点到 ...

  6. 【BZOJ】3160: 万径人踪灭 FFT+回文串

    [题意]给定只含'a'和'b'字符串S,求不全连续的回文子序列数.n<=10^5. [算法]FFT+回文串 [题解]不全连续的回文子序列数=回文子序列总数-回文子串数. 回文子串数可以用回文串算 ...

  7. 【BZOJ4624】农场种植 FFT

    [BZOJ4624]农场种植 Description 农夫约翰想要在一片巨大的土地上建造一个新的农场. 这块土地被抽象为个 R*C 的矩阵.土地中的每个方格都可以用来生产一种食物:谷物(G)或者是牲畜 ...

  8. 【BZOJ3160】万径人踪灭 Manacher+FFT

    [BZOJ3160]万径人踪灭 Description Input Output Sample Input Sample Output HINT 题解:自己想出来1A,先撒花~(其实FFT部分挺裸的) ...

  9. 【BZOJ3771】Triple 生成函数+FFT

    [BZOJ3771]Triple Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: “这把斧头,是不是你的?” 樵夫一看 ...

随机推荐

  1. 【JDBC&Dbutils】JDBC&JDBC连接池&DBUtils使用方法(重要)

    -----------------------JDBC---------- 0.      db.properties文件 driver=com.mysql.jdbc.Driver url=jdbc: ...

  2. Java 关键字有哪些

    数据类型: Boolean(布尔型)    int    long    short    byte    float    double    char    class    interface( ...

  3. Devexpress VCL Build v2013 vol 13.2.4 发布

    不说了,自己看吧. What's New in 13.2.4 (VCL Product Line)   New Major Features in 13.2 What's New in VCL Pro ...

  4. hdu-1107(模拟题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1107 注意:1.路线是要反向的,走不通就反向: 2.输入输出全部是整形 3.攻击力不断变化 #incl ...

  5. js 验证input 输入框

    <h1>js验证输入框内容</h1><br /><br /> 只能输入英文<input type="text" onkeyup ...

  6. 日历时间选择控件---3(支持ie、火狐)

    效果展示:  源代码: <script language=javascript ><!--/* 调用方法:不能用onfocus,要用onclick  <input onclic ...

  7. DIV+CSS实战(五)

    一.说明 前面实现了关键词订阅模块,现在实现站点订阅模块,主要实现的是站点添加界面.站点添加界面里面实现一个提示框不在提示的功能(保存到cookie中),还有就是实现一个站点的选择框,包括输入文字自动 ...

  8. [笔记]python

    配置python apt install python2.7 python3 apt install python-bs4 python3-bs4 apt install virtualenv apt ...

  9. Tensorflow currently has no official prebuild for your CUDA, cuDNN combination.

    INFO CUDA version: 10. ERROR cuDNN not found. See https://github.com/deepfakes/faceswap/blob/master/ ...

  10. Hdu1050 Moving Tables 2016-05-19 16:08 87人阅读 评论(0) 收藏

    Moving Tables Problem Description The famous ACM (Advanced Computer Maker) Company has rented a floo ...