HDU 4609 FFT
2015-10-26 12:28
211 查看
题目大意
给定n条边的边值,求任意取三条边能组成三角形的概率
这里概率 P = valid/tot
tot = (n-2)*(n-1)*n/6是没问题的
valid表示合法的方式
先考虑,任意两条边组合形成方法的总数
因为边值在100000的范围内,这里组合用fft计算
得到最后形成和为 i 的两条边的方法数为 num[i]
这里计算后要记得减去取两条相同边的情况,还有 取 3,4 和 4,3是一样的,要记得除以2
最后跑个n的循环,每次将当前边作为排序后(主要是因为有长度相同的边才这么考虑)次序最大的边,然后保证得到的和是两条在它前面的边组成的
这个计算就需要求个总方法数的前缀和了
取到所有和大于当前边的方法数,减去由两条比它大的边组成的情况(n-i)*(n-i-1)/2,一个比他大一个比他小组成的(n-i)*(i-1),还有它其余任意一条边组成的(n-1)
给定n条边的边值,求任意取三条边能组成三角形的概率
这里概率 P = valid/tot
tot = (n-2)*(n-1)*n/6是没问题的
valid表示合法的方式
先考虑,任意两条边组合形成方法的总数
因为边值在100000的范围内,这里组合用fft计算
得到最后形成和为 i 的两条边的方法数为 num[i]
这里计算后要记得减去取两条相同边的情况,还有 取 3,4 和 4,3是一样的,要记得除以2
最后跑个n的循环,每次将当前边作为排序后(主要是因为有长度相同的边才这么考虑)次序最大的边,然后保证得到的和是两条在它前面的边组成的
这个计算就需要求个总方法数的前缀和了
取到所有和大于当前边的方法数,减去由两条比它大的边组成的情况(n-i)*(n-i-1)/2,一个比他大一个比他小组成的(n-i)*(i-1),还有它其余任意一条边组成的(n-1)
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> using namespace std; #define N 100005 #define ll long long const double PI = acos(-1.0); int n , a , cnt ; ll num[N<<2] , sum[N<<2]; struct complex{ double r , i; complex(double r=0 , double i=0):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 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 i=2 ; i<=len ; i<<=1){ complex wn(cos(-on*2*PI/i) , sin(-on*2*PI/i)); for(int j=0 ; j<len ; j+=i){ complex w(1,0); for(int k=j ; k<j+i/2 ; k++){ complex u = y[k]; complex t = w*y[k+i/2]; y[k] = u+t; y[k+i/2] = u-t; w = w*wn; } } } if(on==-1) for(int i=0 ; i<len ; i++) y[i].r /= len; } complex x[N<<2]; int main() { // freopen("a.in" , "r" , stdin); int T; scanf("%d" , &T); while(T--){ scanf("%d" , &n); int mx = 0; memset(cnt , 0 , sizeof(cnt)); for(int i=1 ; i<=n ; i++){ scanf("%d" , &a[i]); cnt[a[i]]++ , mx=max(mx , a[i]); } int len = 1; while(len<2*(mx+1)) len<<=1; for(int i=0 ; i<=mx ; i++) x[i] = complex(cnt[i] , 0); for(int i=mx+1 ; i<len ; i++) x[i] = complex(0 , 0); fft(x , len , 1); for(int i=0 ; i<len ; i++) x[i] = x[i]*x[i]; fft(x , len , -1); for(int i=0 ; i<len ; i++) num[i] = (ll)(x[i].r+0.5); for(int i=1 ; i<=n ; i++) num[a[i]+a[i]]--; for(int i=0 ; i<len ; i++){ num[i]/=2; if(i) sum[i] = sum[i-1]+num[i]; } ll ans = 0; sort(a+1 , a+n+1); for(int i=1 ; i<=n ; i++){ ll val = sum[len-1]-sum[a[i]]; val = val - (n-1); val = val - (ll)(n-i)*(i-1); val = val - (ll)(n-i)*(n-i-1)/2; // cout<<i<<" "<<a[i]<<" "<<sum[len-1]-sum[a[i]]<<" "<<val<<endl; ans = ans+val; } printf("%.7f\n" , ans*6.0/((ll)n*(n-1)*(n-2))); } return 0; }
相关文章推荐
- Timus Online Judge 1017 Staircases(记忆化搜索)
- Volley android 多key 多File 文件上传,目前只实现了两个key,实现多key请自己改
- 背包之01,完全,多重模板
- MongoDB数组修改器更新数据
- Eclipse没有marketplace选项
- [树莓派]安装node环境
- zabbix web 配置
- poj1114 pig bank 完全背包
- poj2602 bone 0-1背包
- Play 2.0 中文资料 - Play JSON 库
- [No000031]操作系统 Operating Systems 之Open the OS!
- 网络延时-CCF测试往届题(70分)
- Java 299之输出二维数组中的最大值
- Android中ListView Item布局优化技巧
- Unity5 VS UE4
- akka quertz expressions
- iPhone相机拍照的图片的imageOrientation的问题
- caffe安装过程中碰到的一些问题以及解决方案
- [C++]关于数组的引用和引用的数组
- 你可以不知道原因,但是,我们不能停止努力。httplook抓取路由配置界面信息