hdu4609 3-idiots

题意:

给出n个木棍以及它们的长度,求取其中三根长度各不相同的木棍组成三角形的概率

题解:

三角形满足条件:
任意两边之和大于第三边
我们设多项式A(x),其中Cixi(Ci是系数)C_ix^i(C_i是系数)Ci​xi(Ci​是系数)表示长度为i的木棍个数是CiC_iCi​。那么多项式A(x)∗A(x)A(x)*A(x)A(x)∗A(x)中xix^ixi前面的系数表示用两根木棍拼成长度为i的木棍的方案数,多项式相乘利用FFT加速O(nlogn)
对于两根木棍拼成的长度i,只要我们找到一个木棍x长度为j,j小于i,且木棍x为最长,那就是一个合法的三角形
我们维护一个后缀和sum[i]:表示对于所有j>=i,A(x)2A(x)^2A(x)2多项式中xjx^jxj前面的系数和,也就是用两个木根拼成长度大于等于i的方案数
现在我们枚举三根棍子中最长的那根木棍的长度为len,求最长木棍是len,三根木棍互不相同并能组成三角形的方案数。
对于最长为a[i],方案数为sum[a[i]+1],但是要减去很多不合法的情况,看下面的详细讨论

for(int i=1;i<=n;i++)sum[a[i]+a[i]]--;//把自己配自己的情况去掉 for(int i=1;i<=len;i++)sum[i]/=2;//把a和b组合==b和a组合,会重复,除以2 for(int i=len-1;i>=0;i--)sum[i]+=sum[i+1];//求出方案前缀和 ll ans=0;for(int i=1;i<=n;i++){ans+=sum[a[i]+1];//大于a[i]的方案数ans-=1ll*(n-i)*(i-1);//减掉一个大于a[i],一个小于a[i]的情况 ans-=1ll*(n-1);//减去一个选了自己,另一个任意选的情况ans-=1ll*(n-i)*(n-i-1)/2;//减去两个边都大于它的情况}

因为题目要求的是概率,所以再除以Cn3C_n^3Cn3​

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI=acos(-1.0);
struct Complex{double x,y;Complex(double _x=0.0,double _y=0.0){x=_x;y=_y;}Complex operator -(const Complex &b)const{return Complex(x-b.x,y-b.y);}Complex operator +(const Complex &b)const{return Complex(x+b.x,y+b.y);}Complex operator *(const Complex &b)const{return Complex(x*b.x-y*b.y,x*b.y+y*b.x);}
};
void change(Complex y[],int len)
{int i,j,k;for(i=1,j=len/2;i<len-1;i++){if(i<j) swap(y[i],y[j]);k=len/2;while(j>=k){j-=k;k/=2;}if(j<k)j+=k;}
}
void fft(Complex y[],int len,int on)
{change(y,len);for(int h=2;h<=len;h<<=1){Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));for(int j=0;j<len;j+=h){Complex w(1,0);for(int k=j;k<j+h/2;k++){Complex u=y[k];Complex t=w*y[k+h/2];y[k]=u+t;y[k+h/2]=u-t;w=w*wn;}}}if(on==-1)for(int i=0;i<len;i++)y[i].x/=len;
}
const int MAXN=400010;
Complex x1[MAXN],x2[MAXN];
int str1[MAXN/2],str2[MAXN/2],a[MAXN];
ll sum[MAXN];
int t,n;
int main()
{scanf("%d",&t);while(t--){scanf("%d",&n);memset(str1,0,sizeof str1);memset(str2,0,sizeof str2);for(int i=1;i<=n;i++){scanf("%d",&a[i]);str1[a[i]]++;str2[a[i]]++;}sort(a+1,a+n+1);int len1=a[n]+1;int len2=a[n]+1;int len=1;while(len<len1*2||len<len2*2) len<<=1;for(int i=0;i<len1;i++)x1[i]=Complex(str1[i],0);for(int i=len1;i<len;i++)x1[i]=Complex(0,0);for(int i=0;i<len2;i++)x2[i]=Complex(str2[i],0);for(int i=len2;i<len;i++)x2[i]=Complex(0,0);fft(x1,len,1);fft(x2,len,1);for(int i=0;i<len;i++)x1[i]=x1[i]*x2[i];fft(x1,len,-1);for(int i=0;i<len;i++)sum[i]=(ll)(x1[i].x+0.5);len=len1+len2-1;for(int i=1;i<=n;i++)sum[a[i]+a[i]]--;//把自己配自己的情况去掉 for(int i=1;i<=len;i++)sum[i]/=2;//把a和b组合==b和a组合,会重复,除以2 for(int i=len-1;i>=0;i--)sum[i]+=sum[i+1];//求出方案前缀和 ll ans=0;for(int i=1;i<=n;i++){ans+=sum[a[i]+1];//大于a[i]的方案数ans-=1ll*(n-i)*(i-1);//减掉一个大于a[i],一个小于a[i]的情况 ans-=1ll*(n-1);//减去一个选了自己,另一个任意选的情况ans-=1ll*(n-i)*(n-i-1)/2;//减去两个边都大于它的情况}ll w=1ll*n*(n-1)*(n-2)/6;printf("%.7f\n",(double)ans/w);}return 0;
}

hdu4609 3-idiots相关推荐

  1. 解题报告(二)E、(BZOJ3513) [MUTC2013] idiots(生成函数 + FFT + 组合计数)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  2. HDU4609 FFT

    关于这道题请移步kuangbin爷的blog:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html 感觉我一辈子也不能写出这么 ...

  3. bzoj 3513: [MUTC2013]idiots FFT

    bzoj 3513: [MUTC2013]idiots FFT 链接 bzoj 思路 参考了学姐TRTTG的题解 统计合法方案,最后除以总方案. 合法方案要不好统计,统计不合法方案. \(a+b< ...

  4. 《3 idiots 》主题曲Behti Hawa Sa Tha Woh的歌词和mp3下载链接

    20120120 很久没有看到这么好看的励志电影了. 看这部电影以前也没少看国产电影,看了3 idiots以后才发现,中国电影比印度电影差得太多太多了. 借用一段豆瓣上对中国电影的给力评价: &quo ...

  5. BZOJ 3513: [MUTC2013]idiots [FFT]

    统计每种长度的木棒数量,先计算出两根棒子能构成的长度,想到卷积.1.拿这个序列卷积自己 2.计算重算的部分,首先是一条边自己和自己的这种情况,另一种是(i,j)和(j,i)这种形式.第一种,可以枚举读 ...

  6. hdu4609 3idiots 三角形计数 FFT

    直接上代码 #include <iostream> #include <cstdio> #include <cmath> #include <cstring& ...

  7. bzoj 3513: [MUTC2013]idiots【生成函数+FFT】

    想了好长时间最后发现真是石乐志 第一反应就是两边之和大于第三边,但是这个东西必须要满足三次-- 任意的两边之和合通过生成函数套路+FFT求出来(记得去掉重复选取的),然后这任意两边之和大于任意第三边可 ...

  8. 2019.01.02 bzoj3513: [MUTC2013]idiots(fft)

    传送门 fftfftfft经典题. 题意简述:给定nnn个长度分别为aia_iai​的木棒,问随机选择3个木棒能够拼成三角形的概率. 思路:考虑对于木棒构造出生成函数然后可以fftfftfft出两个木 ...

  9. [hdu4609]3-idiots(快速傅利叶变换FFT)

    题目名字是三个制杖- [题意] 有T组数据 每组数据给出n条线段,问任意取三条,可以组成三角形的概率 [输入] 开头一行输入T(T<=10) 下来T组数据,每组数据第一行输入一个n(3<= ...

最新文章

  1. 100万奖金池,这不仅仅是场比赛
  2. 理解MVC—从实例出发:基于MVC模式的简易算术计算器
  3. 乐高科技系列搭建指南 pdf_玩转乐高创意亲子搭建系列(4)小颗粒作品
  4. c语言程序100例pdf,经典c程序100例源代码(全).pdf
  5. html/css表单美化
  6. SEO理论实践的10大误区
  7. 个人理解设计为何要多用组合,少用继承
  8. win7系统配置ntp服务器,技术员教你解决win7系统NTP时间服务器设置的设置方法
  9. 蒙特卡罗方法采样算法
  10. 如何将m4a格式音频转为mp3?
  11. CS很难发论文?这些技巧你都get了吗?
  12. 18、CSS基础——属性值的计算过程
  13. 学生成绩计算的c语言,学生成绩标准管理系统C语言.doc
  14. 服务器阻止程序运行怎么破,Discuz论坛对服务器的请求已遭到某个扩展程序的阻止问题解决方法...
  15. Tumblr创始人David Karp:文艺技术男的成功之路
  16. 超分辨率分析(三)--端到端监督类深度学习方案综述
  17. php 微信分享功能_基于thinkPHP实现的微信自定义分享功能
  18. xshell连接不上linux(centos)
  19. Realvnc虚拟模式下更改分辨率
  20. 曾“伪造”Solana七成TVL的“多重人格者”,正望向Aptos

热门文章

  1. 遇到可爱女生如何搭讪?
  2. 当代年轻人,都有些不成文的规定?
  3. 出现了!豆瓣最高9.9分,2020年最值得看的美剧!你居然还没看过?【内附资源】...
  4. 把 14 亿中国人民都拉到一个微信群里在技术上能实现吗?
  5. 这个被称为20世纪最伟大人物的最强理科生,到底有多强,你根本不了解
  6. 荐书 | 10本书给你计算机大师思维
  7. python运算符号输入_【Python】【运算符】
  8. python从入门到实践django_Django入门——《Python编程从入门到实践》
  9. 怎样让电脑速度变快_硬盘在电脑中起什么作用?
  10. php curl https 443,PHP CURL支持HTTP、HTTPS 请求亲测可用