HDU 4609 3-idiots [FFT]
来源:互联网 发布:淘宝洗车工具大全 编辑:程序博客网 时间:2024/06/08 10:41
题意:给你n个数,求从其中取出3个数能成为三角形的概率
题解:既然要做三角形,所以我们需要,知道两边和的大小,但是两边和的大小需要n^2,所以需要FFT加速卷积计算两边和的情况,我们用num数组记录数字x出现的次数。要减去同一个数用两次的情况,和A与B B与A的情况。
计算出所有两边和的情况后,我们只要枚举每个数,按照枚举第三边大于其他两边的情况就不会重复,所以我们找到所有大于a[i]的两边之和的情况,减去其余边一大一小的情况,其余边都大于a[i]的情况,其中有一条是a[i]的情况,就是答案。(要注意num一共10000*10000总情况会爆int)
AC代码:
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#define MAXN 400040typedef long long ll;using namespace std;const double PI = acos(-1.0);//复数结构体struct complex{ double r,i; complex(double _r = 0.0,double _i = 0.0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complex operator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); }};/* * 进行FFT和IFFT前的反转变换。 * 位置i和 (i二进制反转后位置)互换 * len必须取2的幂 */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]); //交换互为小标反转的元素,i<j保证交换一次 //i做正常的+1,j左反转类型的+1,始终保持i和j是反转的 k = len/2; while( j >= k) { j -= k; k /= 2; } if(j < k) j += k; }}/* * 做FFT * len必须为2^k形式, * on==1时是DFT,on==-1时是IDFT */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].r /= len;}complex x1[MAXN],x2[MAXN];ll num[MAXN],qian[MAXN];int a[MAXN];int main(){int T;scanf("%d",&T);while(T--){memset(num,0,sizeof(num));ll n;scanf("%lld",&n);int ma=0;for(int i=0;i<n;i++){scanf("%d",&a[i]);num[a[i]]++;ma=max(ma,a[i]);}sort(a,a+n);ma++;int len=1;while(len<ma*2)len<<=1; for(int i=0;i<ma;i++)x1[i]=complex(num[i],0);for(int i=ma;i<len;i++)x1[i]=complex(0,0); for(int i=0;i<ma;i++)x2[i]=complex(num[i],0);for(int i=ma;i<len;i++)x2[i]=complex(0,0);//求DFTfft(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++)num[i]=(ll)(x1[i].r+0.5);len=(ma-1)*2;for(int i=0;i<n;i++)//去除本身与本身组成的长度 num[a[i]+a[i]]--;for(int i=1;i<=len;i++)//去除A+B或者B+A的重复情况 num[i]/=2;qian[0]=0;for(int i=1;i<=len;i++)qian[i]=qian[i-1]+num[i];ll cnt=0;for(int i=0;i<n;i++){cnt+=qian[len]-qian[a[i]]; //所有符合的种类 cnt-=(ll)(i)*(n-1-i); //一小一大的情况 cnt-=(n-1); //取到本身的情况 cnt-=(ll)(n-i-1)*(n-i-2)/2; //取到比他大的情况 C(big,2);}ll all=n*(n-1)*(n-2)/6;printf("%.7f\n",(double)cnt/all);}return 0;}
阅读全文
0 0
- HDU 4609 3-idiots (FFT)
- hdu 4609 3-idiots FFT
- hdu 4609 3-idiots (FFT)
- HDU 4609 3-idiots FFT
- 【HDU】4609 3-idiots 【FFT】
- hdu 4609 3-idiots (FFT)
- HDU 4609 3-idiots(FFT)
- HDU 4609 3-idiots [FFT]
- HDU 4609 3-idiots (FFT)
- HDU 4609 3-idiots(FFT)
- hdu 4609 3-idiots 快速傅里叶变换/FFT
- hdu 4609 3-idiots (FFT+计数)
- [HDU 4609]3-idiots(FFT+生成函数)
- 【HDU 4609】3-idiots(FFT)
- HDU 4609 3-idiots FFT+计数问题
- HDU 4609 3-idiots(FFT)
- HDU 4609(3-idiots-FFT+dp)
- hdu 4609 3-idiots FFT 计数
- 1020. 月饼 (25)
- UVA116
- 【java设计模式】之 建造者(Builder)模式
- Tea
- R 语言 导出到MySQL连接不稳定应对
- HDU 4609 3-idiots [FFT]
- spring boot
- Unity3D新手引导开发手记
- IOS 控制器常见问题
- 调整内核printk打印级别--减少启动时的打印信息
- 运用MyBatis查询mysql数据库中的信息
- 阿里云wamp外网访问问题
- 【java设计模式】之 代理(Proxy)模式
- Android四大组件