HDU-4609(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);
    }
}

原文地址:https://www.cnblogs.com/chasedeath/p/12092699.html

时间: 2024-10-11 17:29:56

HDU-4609(FFT/NTT)的相关文章

hdu 4609 FFT

题意:给出一堆数,问从这些数中取3个能组成三角形的概率? sol:其实就是问从这些数里取3个组成三角形有多少种取法 脑洞大开的解法:用FFT 设一开始的数是1 3 3 4 作一个向量x,其中x[i]=边长为i的边的个数 那么就有x=[0 1 0 2 1 0 0 0 0] 令y=x,对x和y作DFT,得到dx和dy.令dn=dx*dy,再对dn作IDFT得到n 那么就得到n=[0 0 1 0 4 2 4 4 1 0 ] 其中n[i]=在x和y中各选一条边,使得两条边之和为i有几种方案 这时得到的n

hdu 4609 3-idiots 【FFT快(gui)速傅立叶变换】

FFT实现起来挺复杂的,开始用vector,结果发现空间超了,换成数组还是超,删掉了几个后又超时了 sin cos 函数调用次数太多了,改成乘法,还是超时 最后把FFT里的除法运算和模运算优化了一下,终于过了,排的老后面 坑,3843MS,一看时间最少的只有671MS,我都怀疑这是不是同一个算法..为毛差距这么大 #pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include

hdu 5885 FFT

XM Reserves Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)Total Submission(s): 99    Accepted Submission(s): 45 Problem Description As an eligible Ingress Resistance Agent you should know your power source, th

FFT/NTT做题方法与调试技巧(+提高码题效率的一些想法)

(其实本文应该写成了"结合FFT讨论的调试技巧+码题方法",语文不好一写文章就偏题QAQ) 有意见欢迎提出,有遗漏欢迎补充! FFT(快速傅里叶变换)/NTT(数论变换)是卷积运算常见而实用的优化 但是FFT/NTT的处理过程并不像暴力运算(差不多是多项式乘法)那样能够直观地反映卷积结果的实时变化. 因此在使用FFT时将会或多或少地加大调试的难度. 如果调试程序时直接跟踪变量,每步手算结果比对,不仅会耽误大量时间,而且效果可能并不理想. 直接肉眼查错效率可能也不太高. 但也正由于FFT

FFT NTT 错误总结(持续更新)

FFT NTT错误总结 1 处理\(r\)数组时忘记赋值 r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1)); 2 负数重载运算符 point operator * (point a,point b){ return point(a.x * b.x - a.y * b.y,a.x * b.y + a.y * b.x); } 3 欧拉公式记不清楚 point Wn = point(cos(Pi / mid),type *

FFT/NTT基础题总结

在学各种数各种反演之前把以前做的$FFT$/$NTT$的题整理一遍 还请数论$dalao$口下留情 T1快速傅立叶之二 题目中要求求出 $c_k=\sum\limits_{i=k}^{n-1}a_i*b_{i-k}$ 首先可以把$a$翻转, $c_k=\sum\limits_{i=k}^{n-1}a_{n-1-i}*b_{i-k}$ $c_k=\sum\limits_{i=0}^{n-k-1}a_{n-k-1-i}*b_{i}$ 也就是说对新的$a$,$b$数组做一遍$FFT$得到的便是$c$数

多项式$fft$,$ntt$,$fwt$初步

最近在学多项式和生成函数. 上课听$lnc$大神讲还是$mengbier$. 作为多项式的前置芝士,$fft,ntt$等是必学的. 在此记录一些关于$fft,ntt,fwt$的知识及例题... FFT: 应用在处理$\sum _{i+j=k} f[i]*g[j]$的卷积上. 看网上大佬的博客,基本入了门吧. 自己的关于原理的一些见解: 多项式有系数表示和点值表示,两种表示方法可以相互转化. FFT可以在$O(n*longn)$内解决多项式乘法. 具体是,点值表示的方法应用在多项式上是$O(n)$

HDU-5730(CDQ+FFT/NTT)

HDU-5730(CDQ+FFT/NTT) 题意:将长度为\(n\)的序列分成若干段,每段\([l,r]\)的权值为\(a_{r-l+1}\),一种分法的权值为所有段的乘积,求所有可能的分法的权值和 根据题意可以得到简单\(dp\) \(dp_0=1,dp_i=\sum_0^{i-1}dp_j \cdot a_{i-j}\) 可以看到是一个\(i-j\)形式的作差卷积 但是直接卷积我们无法保证先求出了\(dp_j\),所有可以用\(CDQ\)分治优化,复杂度\(n\log^2 n\) 具体实现见

HDU 4609 3-idiots fft

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4609 题目描述:给出n个数, 问其中选出三个能组成三角形的概率 解题思路:给出kuangbin巨巨的解题思路, 实在是没有比这儿更好的题解, 所以我就不误导别人和自己了 http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html 题目代码: #include <iostream> #include <cstdio> #