[HDU4609] 3-idiots - 多项式乘法,FFT

题意:有\(n\)个正整数,求随机选取一个3组合,能构成三角形的概率。

Solution: 很容易想到构造权值序列,对其卷积得到任取两条边(可重复)总长度为某数时的方案数序列,我们希望将它转化为两条边不可重复,并去掉顺序。不妨设给定的 \(N\) 个正整数的集合为 \(S\),卷积后的权值序列为 \(\{c_i\}\) ,那么我们对每一个 \(x \in S\), 对 \(c_x\) 减去 \(1\) 即可。

不妨设选出的组合为 \((i,j,k)\),假设 \({x_i}\) 为已经排序的长度序列,那么我们不妨枚举最长边下标 \(k\),那么这一次的贡献为

\[\sum_{k \in S}(\sum_{i=k+1}^{\infty}{c_i})\]

前缀和扫一遍即可。当然问题并没有这么简单,我们这样获得的答案无法满足下列约束条件

\[k \geq i, k \geq j, i \neq k, j \neq k \]

如果所有数字都不同,那么去重将是非常容易的。我们对排序后序列枚举元素下标 \(i \in [0,n)\),那么很显然以 \(i\) 为最大边时非法的共有三类。不妨设\(a_i<a_j\)

满足\(a_i>a_k, a_j>a_k\)的共有

\[\frac{(n-i-1)(n-i-2)}{2}\]

满足\(a_i<a_k, a_j>a_k\)的共有

\[(n-i-1)i\]

满足\(a_i=a_k or a_j=a_k\)的共有

\[n-1\]

于是我们暴力统计一遍就可以得到非法数量,进而得出答案。

原问题是可以出现相同大小的数字的,但容易发现它的去重情况与全部不相同并没有什么差异。因而直接按照上述做法即可得出答案。

我们也可以对这个转化的正确性稍作证明。我们将原始序列中的每一个元素 \(x_i\) 映射到一个新元素

\[y_i = x_i - 0.2 + 0.1 \cdot \frac{i}{n}\]

容易证明\(x_i,x_j,x_k\)可以构成三角形当且仅当\(y_i,y_j,y_k\)可以构成三角形。因此我们通过构造说明了这个转化的正确性。

笔者菜甚,尝试用前缀和直接求解带重复情况失败,留坑在此。

const int N = 200005;
int T,n,m,x[N],a[N],s[N];
double c[N];
double t[N];

int main() {
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--) {
        cin>>n;
        memset(a,0,sizeof a);
        memset(x,0,sizeof x);
        memset(s,0,sizeof s);
        memset(c,0,sizeof c);
        memset(t,0,sizeof t);
        for(int i=0;i<n;i++) cin>>x[i];
        for(int i=0;i<n;i++) m=max(x[i],m);
        for(int i=0;i<n;i++) a[x[i]]++;
        poly p,q;
        p.c.resize(m+1);
        for(int i=0;i<=m;i++) p.c[i]=a[i];
        q=p;
        double ans = 0;
        p*=q;
        for(int i=0;i<=2*m;i++) c[i]=(p.c[i]);
        for(int i=0;i<n;i++) c[x[i]*2]-=1;
        for(int i=0;i<=2*m;i++) c[i]/=2.0;
        t[0]=c[0];
        for(int i=1;i<=2*m;i++) t[i]=t[i-1]+c[i];
        for(int i=0;i<n;i++) ans+=(t[2*m]-t[x[i]]);
        sort(x,x+n);
        for(int i=0;i<n;i++) {
            ans -= (long long)(n-i-1)*(long long)(n-i-2)/2 + (long long)(n-i-1)*(long long)i + (n-1);
        }
        printf("%.7f\n",6.0*(double)ans / ((double)n*(n-1.0)*(n-2.0)));
    }
}

原文地址:https://www.cnblogs.com/mollnn/p/11637945.html

时间: 2024-10-08 01:29:01

[HDU4609] 3-idiots - 多项式乘法,FFT的相关文章

多项式乘法(FFT)学习笔记

------------------------------------------本文只探讨多项式乘法(FFT)在信息学中的应用如有错误或不明欢迎指出或提问,在此不胜感激 多项式 1.系数表示法     一般应用最广泛的表示方式     用A(x)表示一个x-1次多项式,a[i]为$ x^i$的系数,则A(x)=$ \sum_0^{n-1}$ a[i] * $ x^i$ 仅利用这种方式求多项式乘法复杂度为O($ n^2$),不够优秀2.点值表示法     将n个互不相同的值$ x_0$...$

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

[uoj#34] [洛谷P3803] 多项式乘法(FFT)

新技能--FFT. 可在 \(O(nlogn)\) 时间内完成多项式在系数表达与点值表达之间的转换. 其中最关键的一点便为单位复数根,有神奇的折半性质. 多项式乘法(即为卷积)的常见形式: \[ C_n=\sum\limits_{i=0}^n A_iB_{n-i} \] 基本思路为先将系数表达 -> 点值表达 \(O(nlogn)\) 随后点值 \(O(n)\) 进行乘法运算 最后将点值表达 -> 系数表达 \(O(nlogn)\) 代码 #include<cstdio> #inc

luogu3803 多项式乘法 (FFT)

FFT讲解传送门 简单记一下做法: 1.算法流程:两式的系数表达转化为点值表达(O(nlogn))->利用点值表达使两式相乘(O(n))->将结果的点值表达转化回系数表达(O(nlogn)) 2.做法: $$目标:把一个n项多项式F(x)=\sum_{i=0}^{n-1}a_ix^i转化为\{(w^k_n,y_k)\}的点值表达,其中w^k_n为n次单位根的k次方$$ 不妨设n为2的幂次,如果不是,则可以补上系数为0的高次项 $$将a_ix^i按照幂次奇偶性分组,得到F(x)=(a_0x^0+

UOJ #34 多项式乘法 FFT快速傅立叶变换

题目大意:这是一道模板题. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1000010 using namespace std; const double PI = acos(-1.0); struct Complex{ double x,y; Complex(dou

【模版】多项式乘法 FFT

https://www.luogu.org/problem/show?pid=3803 题目背景 这是一道模版题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 1 2 1 2 1

LibreOJ #108. 多项式乘法

二次联通门 : LibreOJ #108. 多项式乘法 /* LibreOJ #108. 多项式乘法 FFT板子题 不行啊...跑的还是慢 应该找个机会学一学由乃dalao的fft 或者是毛爷爷的fft,跑的真是快啊... */ #include <cstdio> #include <iostream> #include <cmath> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void re

FFT多项式乘法学习笔记

??其实我不知道我是否真的理解了FFT,但是我会用FFT优化多项式乘法了QAQ.. (以下大多摘自算导 前置知识 1. 多项式 ??在一个代数域F上,关于变量x的多项式定义为形式和形式表示的函数 A(x)=∑j=0n?1ajxj,其中a0-an?1为多项式各项的系数 2. 多项式的次数界 ??若多项式有非零系数的最高次项为xk,则称k为该多项式的次数,任何严格大于k的整数都是这个多项式的次数界. 3. 多项式的表示 (1)系数表示法 ??对于一个次数界为n的多项式A(x)来说,其系数表示法可以看

洛谷P3803 【模板】多项式乘法(FFT)

P3803 [模板]多项式乘法(FFT) 题目背景 这是一道FFT模板题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 复制 1 2 1 2 1 2 1 输出样例#1: 复制 1