2019hdu多校第一场H Desert [多项式计数] [仙人掌计数]
首先注意到n个点的仙人掌其实和n个圆点的圆方树是等价的,那么转化为求圆方树的统计会简单一点。
圆方树要满足的性质有以下几条:
1.奇数层为圆点,偶数层为方点,即只存在圆点和方点连的边。
2.圆点下的子树是不计顺序的(即仙人掌中一个点连出去几个环没关系)。
3.方点下的子树和顺序有关系,但正反相同的顺序视为一样(即仙人掌中环上的点顺序是有影响的,并且正反顺序是相同的)。
一般来讲,正反顺序视为相同的套路都是把回文的加上再除以2.
记 f n f_n fn为以圆点为根的有 n n n个圆点的圆方树个数, g n g_n gn为以方点为根的有 n n n个圆点的圆方树个数。
再设 g 1 n g1_n g1n为有 n n n个圆点的以圆点为根的圆方树森林, g 2 n g2_n g2n为有 n n n个圆点的奇数棵圆方树森林, g 3 n g3_n g3n为有 n n n个圆点的偶数棵圆方树森林,则直接考虑暴力的话有:
g 1 n = ∑ i = 1 n g 1 n − i ⋅ f i g1_n=\sum_{i=1}^ng1_{n-i}\cdot f_i g1n=∑i=1ng1n−i⋅fi
g 2 n = ∑ i = 1 n g 3 n − i ⋅ f i g2_n=\sum_{i=1}^ng3_{n-i}\cdot f_i g2n=∑i=1ng3n−i⋅fi
g 3 n = [ 2 ∣ n ] g 1 n 2 g3_n=[2|n]g1_{\frac{n}2} g3n=[2∣n]g12n
g n = g 1 n + g 2 n + g 3 n 2 g_n=\frac{g1_n+g2_n+g3_n}2 gn=2g1n+g2n+g3n
而 f n f_n fn则等价于在 g [ 1... n − 1 ] g[1...n-1] g[1...n−1]中选出总点数为n-1的方点子树,即做一遍完全背包。
直接暴力复杂度肯定是不对的, g 1 , g 2 , g 3 , g g1,g2,g3,g g1,g2,g3,g的计算容易用 N T T NTT NTT加速,下面考虑如何快速计算 f n f_n fn.
(以下部分涉及到2015年集训队论文)
记 f ( x ) = ∑ i = 1 ∞ f n x n − 1 f(x)=\sum_{i=1}^\infty f_nx^{n-1} f(x)=∑i=1∞fnxn−1,并对每种 g i g_i gi写出生成函数,相乘后有 f ( x ) = ∏ i ( 1 + x + x 2 + ⋯   ) g i = ∏ i ( 1 1 − x i ) g i f(x)=\prod_i(1+x+x^2+\cdots)^{g_i}=\prod_i(\frac1{1-x^i})^{g_i} f(x)=∏i(1+x+x2+⋯)gi=∏i(1−xi1)gi.
两边取对数: ln f ( x ) = − ∑ i g i ⋅ l n ( 1 − x i ) = ∑ i g i ⋅ ∑ j = 1 ∞ x i j j \ln f(x)=-\sum_i g_i\cdot ln(1-x^i)=\sum_ig_i\cdot\sum_{j=1}^\infty\frac{x^{ij}}j lnf(x)=−∑igi⋅ln(1−xi)=∑igi⋅∑j=1∞jxij.
两边取导数: d d x ln f ( x ) = f ′ ( x ) f ( x ) = ∑ i = 1 ∞ ( n − 1 ) f n x n − 2 ∑ i = 1 ∞ f n x n − 1 \frac d{dx} \ln f(x)=\frac{f'(x)}{f(x)}=\frac{\sum_{i=1}^\infty(n-1)f_nx^{n-2}}{\sum_{i=1}^\infty f_nx^{n-1}} dxdlnf(x)=f(x)f′(x)=∑i=1∞fnxn−1∑i=1∞(n−1)fnxn−2.
d d x ( ∑ i g i ⋅ ∑ j = 1 ∞ x i j j ) = ∑ i g i ⋅ ∑ j = 1 ∞ i ⋅ x i j − 1 = ∑ i i g i ⋅ ∑ j = 1 ∞ x i j − 1 \frac d{dx}(\sum_ig_i\cdot\sum_{j=1}^\infty\frac{x^{ij}}j)=\sum_ig_i\cdot\sum_{j=1}^\infty i\cdot x^{ij-1}=\sum_iig_i\cdot\sum_{j=1}^\infty x^{ij-1} dxd(∑igi⋅∑j=1∞jxij)=∑igi⋅∑j=1∞i⋅xij−1=∑iigi⋅∑j=1∞xij−1
即: ∑ i = 1 ∞ ( n − 1 ) f n x n − 2 ∑ i = 1 ∞ f n x n − 1 = ∑ i i g i ⋅ ∑ j = 1 ∞ x i j − 1 \frac{\sum_{i=1}^\infty(n-1)f_nx^{n-2}}{\sum_{i=1}^\infty f_nx^{n-1}}=\sum_iig_i\cdot\sum_{j=1}^\infty x^{ij-1} ∑i=1∞fnxn−1∑i=1∞(n−1)fnxn−2=∑iigi⋅∑j=1∞xij−1 .
即: ∑ i = 1 ∞ ( n − 1 ) f n x n − 2 = ( ∑ i = 1 ∞ f n x n − 1 ) ⋅ ( ∑ i i g i ⋅ ∑ j = 1 ∞ x i j − 1 ) \sum_{i=1}^\infty(n-1)f_nx^{n-2}=(\sum_{i=1}^\infty f_nx^{n-1})\cdot(\sum_iig_i\cdot\sum_{j=1}^\infty x^{ij-1}) ∑i=1∞(n−1)fnxn−2=(∑i=1∞fnxn−1)⋅(∑iigi⋅∑j=1∞xij−1).
为了形式好看,两边再乘以 x 2 x^2 x2: ∑ i = 1 ∞ ( n − 1 ) f n x n = ( ∑ i = 1 ∞ f n x n ) ⋅ ( ∑ i i g i ⋅ ∑ j = 1 ∞ x i j ) \sum_{i=1}^\infty(n-1)f_nx^n=(\sum_{i=1}^\infty f_nx^n)\cdot(\sum_iig_i\cdot\sum_{j=1}^\infty x^{ij}) ∑i=1∞(n−1)fnxn=(∑i=1∞fnxn)⋅(∑iigi⋅∑j=1∞xij)
继续化简等式右边地第二个括号,令 t = i j t=ij t=ij并交换求和顺序: ∑ i i g i ⋅ ∑ j = 1 ∞ x i j = ∑ t = 1 ∞ x t ⋅ ∑ i ∣ t i g i \sum_iig_i\cdot\sum_{j=1}^\infty x^{ij}=\sum_{t=1}^\infty x^t\cdot\sum_{i|t}ig_i ∑iigi⋅∑j=1∞xij=∑t=1∞xt⋅∑i∣tigi
即: ∑ i = 1 ∞ ( n − 1 ) f n x n = ( ∑ i = 1 ∞ f n x n ) ⋅ ( ∑ t = 1 ∞ x t ⋅ ∑ i ∣ t i g i ) \sum_{i=1}^\infty(n-1)f_nx^n=(\sum_{i=1}^\infty f_nx^n)\cdot(\sum_{t=1}^\infty x^t\cdot\sum_{i|t}ig_i) ∑i=1∞(n−1)fnxn=(∑i=1∞fnxn)⋅(∑t=1∞xt⋅∑i∣tigi)
特别地,两边对应项系数相等: ( n − 1 ) f n = ∑ i ( ∑ j ∣ i j g j ) f n − i (n-1)f_n=\sum_i(\sum_{j|i}jg_j)f_{n-i} (n−1)fn=∑i(∑j∣ijgj)fn−i,即 f n = 1 n − 1 ∑ i ( ∑ j ∣ i j g j ) f n − i f_n=\frac1{n-1}\sum_i(\sum_{j|i}jg_j)f_{n-i} fn=n−11∑i(∑j∣ijgj)fn−i.
若令 f t n = ∑ j ∣ i j g j ft_n=\sum_{j|i}jg_j ftn=∑j∣ijgj,则 f n = 1 n − 1 ∑ i f t i f n − i f_n=\frac1{n-1}\sum_ift_if_{n-i} fn=n−11∑iftifn−i.
注意到这也是一个卷积的形式,结合上面的 g 1 , g 2 , g 3 , g g1,g2,g3,g g1,g2,g3,g,直接上分治 F F T FFT FFT即可。
注意特判 f 1 = 1 f_1=1 f1=1。
#include<bits/stdc++.h>
#define maxn 500050
#define inv2 499122177
#define modu 998244353
using namespace std;
typedef long long LL;LL pw(LL a,LL k=modu-2) {LL ans=1;for (;k;k>>=1) {if (k&1)ans=ans*a%modu;a=a*a%modu;}return ans;
}struct NTT {LL I,w[maxn];int N,rev[maxn];void init(int n) {for (N=1;N<n;N<<=1); I=pw(N);rev[0]=0,rev[1]=N>>1;for (int i=2;i<N;++i)rev[i]=rev[i>>1]>>1|rev[i&1];w[0]=1,w[1]=pw(3,(modu-1)/N);for (int i=2;i<N;++i)w[i]=w[i-1]*w[1]%modu;}void DFT(LL *A) {for (int i=0;i<N;++i)if (i<rev[i])swap(A[i],A[rev[i]]);for (int len=2;len<=N;len<<=1) {int m=len>>1;for (LL *p=A;p!=A+N;p+=len)for (int i=0;i<m;++i) {LL u=p[i],v=p[i+m]*w[N/len*i]%modu;p[i]=(u+v)%modu;p[i+m]=(u-v+modu)%modu;}}}void IDFT(LL *A) {DFT(A);reverse(A+1,A+N);for (int i=0;i<N;++i)A[i]=A[i]*I%modu;}
} T;int n;LL I[maxn]={1,1};// inverse of iLL f[maxn];//n node cactus i.e. n circle node yuan fang tree.
LL g[maxn];//n node cactus sequence (no symmetry)
LL ft[maxn];//\sum_{j|i} j*g_j
LL g1[maxn];//n node cactus squence (can be symmetric)
LL g2[maxn];//n node cactus symmetric squence with odd length
LL g3[maxn];//n node cactus symmetric squence with even lengthLL ta[maxn],tb[maxn],tc[maxn];void add(LL &a,LL b) {a=(a+b)%modu;
}void clear(LL *A) {for (int i=0;i<T.N;++i) A[i]=0;
}void contri(int l1,int r1,int l2,int r2,int l3,int r3) {clear(ta),clear(tb);for (int i=l1;i<=r1;++i) ta[i-l1]=f[i];T.DFT(ta);auto calc=[&](LL *c,LL *b) {clear(tb);for (int i=l2;i<=r2;++i) tb[i-l2]=b[i];T.DFT(tb);for (int i=0;i<T.N;++i) tc[i]=ta[i]*tb[i]%modu;T.IDFT(tc);for (int i=0;i<T.N;++i) {int t=i+l1+l2;if (l3<=t&&t<=r3)add(c[t],tc[i]);}};calc(f,ft);calc(g1,g1);calc(g2,g3);
}void solve(int l,int r) {if (l==r) {if (l==1)f[l]=1;elsef[l]=f[l]*I[l-1]%modu;add(g1[l],f[l]);add(g2[l],f[l]);if (~l&1) g3[l]=g1[l>>1];g[l]=(g1[l]+g2[l]+g3[l])*inv2%modu;for (int j=l;j<=n;j+=l)add(ft[j],l*g[l]);return ;}int mid=(l+r)>>1;solve(l,mid);T.init(r-l<<1);auto calc=[&](int l1,int r1,int l2,int r2) {contri(l1,r1,l2,r2,mid+1,r);};if (l>1) calc(l,mid,1,r-l),calc(1,r-l,l,mid);calc(l,mid,l,mid);solve(mid+1,r);
}void brute() {for (int i=1;i<=n;++i) {if (i==1) f[1]=1;else {for (int j=1;j<i;++j) add(f[i],f[i-j]*ft[j]);for (int j=1;j<i;++j) add(g1[i],f[i-j]*g1[j]);for (int j=1;j<i;++j) add(g2[i],f[i-j]*g3[j]);f[i]=f[i]*I[i-1]%modu;}add(g1[i],f[i]);add(g2[i],f[i]);if (~i&1) g3[i]=g1[i>>1];g[i]=(g1[i]+g2[i]+g3[i])*inv2%modu;for (int j=i;j<=n;j+=i) add(ft[j],i*g[i]);}
}int main() {scanf("%d",&n);for (int i=2;i<=n;++i) I[i]=modu-modu/i*I[modu%i]%modu;solve(1,n);// brute();for (int i=1;i<=n;++i)printf("%lld\n",f[i]);return 0;
}
2019hdu多校第一场H Desert [多项式计数] [仙人掌计数]相关推荐
- 2019HDU多校第一场1001 BLANK (DP)(HDU6578)
2019HDU多校第一场1001 BLANK (DP) 题意:构造一个长度为n(n<=10)的序列,其中的值域为{0,1,2,3}存在m个限制条件,表示为 l r x意义为[L,R]区间里最多能 ...
- FFT ---- 2021牛客多校第一场 H Hash Function
题目链接 题目大意: 解题思路: 首先我们知道任意两个数%seed\%seed%seed都不相同→\rightarrow→(aj−ai)%seed≠0(∀ai≤aj)(a_j-a_i)\%seed\n ...
- [2019HDU多校第一场][HDU 6578][A. Blank]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题目大意:长度为\(n\)的数组要求分别填入\(\{0,1,2,3\}\)四个数中的任意一个,有 ...
- [2019HDU多校第一场][HDU 6590][M. Code]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6590 题目大意(来自队友):二维平面上有\(n\)个点,每个点要么是黑色要么是白色,问能否找到一条直线 ...
- 2019HDU多校第一场 HDU6578 Blank
http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意:一排有N个空格.空格从左到右依次为1.2.-.N. 汤姆正在用{0,1,2,3}中的一个数字填充每个 ...
- 2019牛客多校第一场
2019牛客多校第一场 题号 题目 知识点 A Monotonic Matrix B Symmetric Matrix C Fluorescent 2 D Two Graphs E Removal F ...
- 2020 牛客多校第一场
2020 牛客多校第一场 A. B-Suffix Array 后缀数组的思想:倍增+桶排序的方式找出一串连续序列后缀的大小.虽说正常使用的时候都是字典序,但是只要修改排序方式,也能够达到一个类似的&q ...
- 2019年杭电多校第一场 1001题blank(DP)HDU6578
2019年杭电多校第一场 1001题blank(DP)HDU6578 解决思路,开一个DP数组来存储0 1 2 3四个字符最后出现的位置,并且在DP中已经==排好序==. DP开四维,DP[i][j] ...
- python字符串去重及排序 牛客_2018牛客多校第一场 D.Two Graphs
题意: n个点,m1条边的图E1,n个点,m2条边的图E2.求图E2有多少子图跟图E1同构. 题解: 用STL的全排列函数next_permutation()枚举映射.对于每一种映射枚举每一条边判断合 ...
最新文章
- 联发科首发台积电4nm,新旗舰多核跑分与苹果A15不相上下,网友:MTK也要Yes了?...
- php errorcode,php中pdo错误处理方法详解
- 链表题目--2 求链表的中间结点 和 求链表中倒数第k个结点
- 9-算法 希尔排序 shell_sort
- MySQL binlog相关分析
- 非期望产出的sbm模型_线性模型 vs. Logistic模型——离散选择模型之二
- 如何修复最常见的 macOS 11 Big Sur 问题?
- STL容器-queue队列
- 二、设置开发、运行环境 (基础教程2)
- 为什么要在MD5加密的密码中加“盐”
- 时间序列相似性度量-DTW
- es java 创建索引_Elasticsearch(ES) 创建索引
- Validation failed判断错误
- php获取手机本地,PHP通过API获取手机号码归属地
- jsp高级DOM和BOM
- 操作系统文件管理之FCB
- Docker-windows使用教程
- 一篇文章读懂什么是大数据
- linux查询网卡是百兆还是千兆,查看网卡是百兆还是千兆
- 了解你的敌人:跟踪僵尸网络