zoukankan      html  css  js  c++  java
  • HDU4609 3idiots (FFT/NTT)

    HDU-4609(FFT/NTT)

    题意: 给出n个木棒,现从中不重复地选出3根来,求能拼出三角形的概率。

    计算合法概率容易出现重复,所以建议计算不合法方案数

    枚举选出的最大边是哪条,然后考虑剩下两条边之和小于等于它

    两条边之和为\(x\)的方案数可以\(FFT/NTT\)得到,是一个简单的构造

    \(f(x)=\sum x^{length_i}\),求出\(f(x)^2\),就能得到和的方案数,但是会重复,包括自己和自己算,一对算两次

    处理一下前缀和即可

    #include<bits/stdc++.h>
    using namespace std;
    
    #define reg register
    typedef long long ll;
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } 
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); } 
    
    char IO;
    int rd(){
    	int s=0,f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const double PI=acos(-1);
    const int N=262150,P=998244353;
    const int g=3;
    
    int n,m;
    int b[100010];
    int rev[N];
    typedef complex <double> Cp;
    Cp d[N];
    ll a[N];
    
    void FFT(int n,Cp *a,int f){
    	rep(i,0,n-1) if(rev[i]>i) swap(a[i],a[rev[i]]);
    	for(reg int i=1;i<n;i<<=1) {
    		Cp w(cos(PI/i),f*sin(PI/i));
    		for(reg int l=0;l<n;l+=i*2) {
    			Cp e(1,0);
    			for(reg int j=l;j<l+i;j++,e=e*w) {
    				Cp t=a[j+i]*e;
    				a[j+i]=a[j]-t;
    				a[j]=a[j]+t;
    			}
    		}
    	}
    }
    
    int main(){
    	rep(kase,1,rd()) {
    		n=rd();
    		int ma=0;
    		rep(i,1,n) b[i]=rd(),d[b[i]]+=Cp(1,0),ma=max(ma,b[i]);
    		int R=1,c=0;
    		while(R<=ma*2) R<<=1,c++;
    		rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<<(c-1));
    		FFT(R,d,1);
    		rep(i,0,R-1) d[i]=d[i]*d[i];
    		FFT(R,d,-1);
    		rep(i,0,R-1) a[i]=(ll)(d[i].real()/R+0.5);
    		rep(i,1,n) a[b[i]*2]--;
    		rep(i,1,R) a[i]/=2;    //处理重复情况
    		rep(i,1,R) a[i]+=a[i-1];
    		ll ans=0,sum=0;
    		rep(i,1,n) {
    			ans+=a[b[i]]; // 计算不合法方案数
    			sum+=1ll*(i-1)*(i-2)/2;
    		}
    		rep(i,0,R+3) a[i]=0,d[i]=Cp(0,0);
    		rep(i,0,ma+3) b[i]=0;
    		ans=sum-ans;
    		printf("%.7lf\n",1.0*ans/sum);
    	}
    }
    
    
  • 相关阅读:
    Python学习(五)函数 —— 自定义函数
    Python学习(四)数据结构 —— dict
    Python学习(四)数据结构 —— set frozenset
    C++ —— 构建开源的开发环境
    Oracle 数据库 Database Express Edition 11g Release 2 (11.2) 错误解决集锦(使用语法)
    Web —— tomcat 问题解决
    web —— jsp笔记
    Web 前端 —— javaScript
    编程杂谈—— 浮点数
    Web —— java web 项目开发 笔记
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12092699.html
Copyright © 2011-2022 走看看