ntt

FFT/NTT/MTT学习笔记

夙愿已清 提交于 2020-01-21 14:28:26
FFT/NTT/MTT Tags:数学 作业部落 评论地址 前言 这是网上的优秀博客 并不建议初学者看我的博客,因为我也不是很了解FFT的具体原理 一、概述 两个多项式相乘,不用 \(N^2\) ,通过 \(FFT\) 可以把复杂度优化到 \(O(NlogN)\) , \(NTT\) 能够取模, \(MTT\) 可以对非 \(NTT\) 模数取模,相对来说 \(FFT\) 常数小些因为不要取模 二、我们来背板子(FFT) 先放一个板子( 洛谷P3803 【模板】多项式乘法(FFT) ) #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> using namespace std; const int MAXN=3000005; const double pi=acos(-1); int N,M,r[MAXN],l; struct Complex { double rl,im;//real part / imaginary part Complex(){rl=im=0;}//以下是初始化的板子,虽然不懂为什么可以这样写 Complex(double a,double b){rl=a,im=b;} Complex operator + (Complex B) {return Complex(rl+B

luoguP5860 「SWTR-03」Counting Trees 生成函数+多项式exp

情到浓时终转凉″ 提交于 2020-01-18 16:36:16
标签:生成函数,多项式exp 有 $n$ 个点,每个点有一个度数 $v[i]$,代表如果选择这个点就必须满足这个点与 $v[i]$ 条边相连. 求:有多少种选法,使得所选集合中的点能构成一棵树. 如果 $m$ 个点能生成一颗树,那么一定满足 $\sum v_{i}=2\times (m-1)$ 这是因为度数之和其实就是边的数量 $\times 2$. ~~然后感性理解~~:如果 $m$ 个点满足 $\sum v_{i}=2\times(m-1)$,则一定能构成一棵树. 那就将问题转化成:有 $m$ 个物品,每个物品的价值为 $v_{i}-2$,求装满一个体积为 $-2$ 的背包有多少种选法. 对于所有 $v_{i}-2>0$ 的部分,我们直接设生成函数+多项式 exp 来做,然后 $v_{i}=2$ 的部分直接乘上贡献. 最后 $v_{i}=1$ 的部分直接来一个二项式定理展开,然后依次枚举 $v_{i}=1$ 的个数就好了. 因为有 $ori-i=-2$,所以有 $ori=i-2$. code: #include <cmath> #include <cstring> #include <algorithm> #include <cstdio> #include <string> #define ll long long #define ull unsigned long long

LG5828 边双连通图计数

泄露秘密 提交于 2020-01-12 18:04:49
边双连通图计数 求 \(n\) 个点的有标号边双连通图(简单无向图,整个图是一个边双连通分量)的个数,答案对 \(998244353\) 取模。 \(n \leq 10^5\) 。 题解 https://www.luogu.com.cn/blog/user13052/solution-p5828 设有根连通无向图的指数生成函数是 \(F(x)\) 。显然有根就在无根的情况下选一个根出来就行了。 设有根边双连通图的指数生成函数是 \(G(x)\) 。用 \(G\) 来表示 \(F\) : 假设根所在边双大小 \(n\) ,其EGF为 \(g_n\frac{x^n}{n!}\) ,而对于向外连的桥边中的一条,它挂着一个连通无向图,接在边双的任意一个点上,所以得到它的EGF为 \(nF(x)\) ;可以往外挂若干个连通无向图,故EGF是 \(\exp(nF(x))\) 。所以 \[ F(x)=\sum_{i=1}^\infty g_i\frac{x^i}{i!}\exp(iF(x))\\ =\sum_{i=1}^nb_i\frac{x^i}{i!}(\exp F(x))^i=G(x\exp F(x)) \] 设 \(H(x)=x\exp F(x)\) 则 \(F(x)=G(H(x))\) 。两边对用 \(H^{-1}(x)\) 代换 \(x\) 得 \(G(x)=F(H^{-1}(x))

LOJ6538 烷基计数

爱⌒轻易说出口 提交于 2020-01-12 15:54:19
烷基计数 现在已知碳原子个数 \(n\) ,求对应的烷基有多少种同分异构体。 注意:这里的烷基计数不用考虑空间异构,能否稳定存在等各种特殊情况。也就是说,你要求的是 \(n\) 个点的每个点度数不超过 \(4\) 且根的度数不超过 \(3\) 的有根树的数目 。 答案对 \(998244353\) 取模。 题解 https://jkloverdcoi.github.io/2019/12/19/Loj-6538-%E7%83%B7%E5%9F%BA%E8%AE%A1%E6%95%B0-%E5%8A%A0%E5%BC%BA%E7%89%88-%E5%8A%A0%E5%BC%BA%E7%89%88/ 记答案的生成函数为 \(F(x)\) 。直接 \(F(x)=1+xF(x)^3\) 显然是错的,因为可能出现同构的情况。 考虑 Burnside 引理,对 \(3\) 个儿子的置换有 \(6\) 种。 对于 \((1,2,3)​\) 这 \(1​\) 种置换,每种方案都是不动点。 对于 \((1,3,2),(3,2,1),(2,1,3)\) 这 \(3\) 种置换,只有在置换中成环的两棵子树相同的方案才是不动点。 对于 \((2,3,1),(3,1,2)\) 这 \(2​\) 种置换,只有三棵子树都相同的方案才是不动点。 根据 Burnside 引理

UOJ335 生成树计数

无人久伴 提交于 2020-01-07 21:35:14
多项式变量添系数求和 给一个 \(t\) 次多项式 \(P\) 和 \(n\) 个数 \(a_1\sim a_n\) ,求 \(\sum_{i=1}^n P(a_ix)\) 。 题解 若 \(P=\sum_{k=0}^t p_kx^k\) 那么 \[ \sum_{i=1}^n P(a_ix)=\sum_{k=0}^t p_k\sum_{i=1}^n a_i^kx^k \] 先求 \(A\) 的 \(0\sim t\) 次等指数幂和 \(s_A(x)=\sum_{k=0}^\infty x^k \sum_{i=1}^na_i^k\) ,然后与 \(P\) 的系数对位相乘即可。 等指数幂和用 \[ s_A(x)=\sum_{i=1}^n\frac{1}{1-a_ix}=\frac{\sum_{i=1}^n\prod_{j\ne i}(1-a_jx)}{\prod_{i=1}^n(1-a_ix)} \] 求出,时间复杂度 \(O(n\log^2n+t\log t)\) 。 考虑 \(\sum_{i=1}^n\prod_{j\ne i}(1-a_jx)\) 与 \(\prod_{i=1}^n(1-a_ix)\) 的关系。可以发现后者任意 \(i\) 次项在前者中恰好被算了 \(n-i\) 次。所以用分治NTT求出后者后简单处理即可得到求前者。 多项式变量添系数求积 给一个 \(t\)

WC2019

余生颓废 提交于 2020-01-07 03:24:05
数树 Luogu LOJ UOJ 不管怎样先特判 \(y=1\) 的情况。 先考虑固定一棵树的情况。 设固定的树的边集为 \(E_1\) ,枚举的树的边集为 \(E_2\) 。 设 \(f(T)=y^{n-|T|}\) ,那么 \(ans=\sum\limits_{E_2}f(E_1\cap E_2)\) 。 考虑经典子集反演 \[f(T)=\sum\limits_{S\subseteq T}\sum\limits_{R\subseteq S}(-1)^{|S|-|R|}f(R)\] 因此我们有 \[ans=\sum\limits_{E_2}\sum\limits_{S\subseteq E_1\wedge S\subseteq E_2}\sum\limits_{T\subseteq S}(-1)^{|S|-|T|}y^{n-|T|}=\sum\limits_{S\subseteq E_1}(\sum\limits_{S\subseteq E_2}1)\sum\limits_{T\subseteq S}(-1)^{|S|-|T|}y^{n-|T|}\] 设 \(g(S)=\sum\limits_{S\subseteq E_2}1\) 即包含 \(S\) 的树的个数,则有 \[ans=\sum\limits_{S\subseteq E_1}g(S)\sum\limits_{T

多项式快速插值

瘦欲@ 提交于 2020-01-02 21:08:47
200+行的多项式板子题真爽啊 给定 \(n\) 个点的点值 \((x_i,y_i)\) ,求这 \(n\) 个点确定的 \(n-1\) 次多项式 \(n\le 10^5\) 前置知识: 多项式多点求值 拉格朗日插值 微积分基础 首先我们有一个 \(n^2\) 的拉格朗日插值法 \[f(x)=\sum\limits_{i=1}^{n}y_i\prod\limits_{i\ne j}\frac{x-x_j}{x_i-x_j}\] 然后我们学习一个WC2017挑战就过了 考虑优化,我们知道这个形式它很死,把它变成重心插值 \[f(x)=\sum\limits_{i=1}^{n}\frac{y_i}{\prod\limits_{i\ne j}x_i-x_j}\prod\limits_{i\ne j}(x-x_j)\] 发现除了一个常数 \(y_i\) 剩下的就是 \(\prod\limits_{i\ne j}(x-x_i)\) 的形式了,我们设它为 \(g(x)\) 那么前面那一项的分母可以表示为 \(\frac{g(x)}{x-x_i}(x=x_i)\) 发现 \(x=x_i\) 时分子分母都是 \(0\) 根据洛必达法则 \[\lim\limits_{x→x_i}\frac{g(x_i)}{x-x_i}=\lim\limits_{x→x_i}\frac{g'(x_i)}{(x-x_i

多项式指数函数

岁酱吖の 提交于 2020-01-02 08:17:18
给定 \(n-1\) 次多项式 \(A(x)\) ,求一个 \(mod\, x^n\) 下的多项式 \(B(x)\) ,满足 \(B(x)≡e^{A(x)}\) ,系数对 \(998244353\) 取模 一大堆前置姿势: 微积分 多项式对数函数 多项式牛顿迭代 计算 \(F(x)≡e^{A(x)}(mod\, x^n)\) 两边同时取对数得 \(lnF(x)-A(x)≡0 (mod\, x^n)\) 设 \(G(F(x))=lnF(x)-A(x)(mod\, x^n)\) 套一下牛顿迭代公式 \(F(x)=F_0(x)-\frac{G(F(x))}{G'(F_0(x))}(mod\, x^n)\) \(A(x)\) 是给定的常数项,那么 \(G'(x)=G(x)^{-1}\) 可以整理出来 \(F(x)=F_0(x)(1-lnF_0(x)+A(x))(mod\, x^n)\) 然后递归求解,注意边界为 \(F(0)=1\) #include<bits/stdc++.h> using namespace std; namespace red{ #define int long long #define eps (1e-8) inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!=

「PKUSC2018」神仙的游戏

给你一囗甜甜゛ 提交于 2019-12-26 21:51:34
题目链接 比如说上面 \(|S|\) 为12的字符串,我们欲求出 \(f(9)\) 的值,那么上面相同颜色的字符必须两两能够匹配。也就是说,同种颜色的字符集里不能同时出现0和1。如果只考虑同种颜色集里相邻的两个字符能否匹配,那么小样例都过不了。。 我们仔细观察就会发现,每隔 \(|S|-len\) 的位置就会出现相同的字符。我们可以认为长度为 \(len\) 的border实质上就是将长度为 \(len\) 的前缀向后偏移 \(|S|-len\) ,看是否能匹配。 如果有两个字符 \(s[i],s[j]\ (i<j)\) ,他们一个是0,一个是1,那么偏移量就不能为 \(j-i\) 。于是我们定义一个数组 \(illegal\) 。 \(illegal[i]\) 为1表示偏移量为 \(i\) 时不合法。 假设我们已经求出了 \(illegal\) 数组,我们判断 \(f(len)\) 的值,那么我们只需判断 \(illegal[|S|-len]\) 就可以了吗?当然不行,因为我们说了是字符集中不同时出现0和1,只判断 \(illegal[|S|-len]\) 相当于只判断了相邻两个字符能否匹配。所以我们还要判断 \(|S|-len\) 的倍数。 至于求 \(illegal\) ,就是经典的 \(FFT/NTT\) 在字符串匹配中的引用。可以构造一个反串,然后正反串做 \(NTT\)

BZOJ5372 PKUSC2018神仙的游戏(NTT)

筅森魡賤 提交于 2019-12-26 21:51:14
  首先有一个想法,翻转串后直接卷积看有没有0匹配上1。但这是必要而不充分的因为在原串和翻转串中?不能同时取两个值。   先有一些结论:   如果s中长度为len的前缀是border,那么其存在|s|-len的循环节(最后一段不一定完整)。   如果已知len不是s的循环节,那么显然len的因子也不是s的循环节。   如果位置差为len的两个位置无法匹配,那么len不是s的循环节。   于是可得:如果位置差为len的两个位置无法匹配,那么长度为|s|-(len的因子)的前缀不是border。   可以发现其实问号出现冲突的原因就在于此,即某两个01的位置差为len,而问号在两者之间且与其中一个的位置差是len的因子。   那么这是充分的,即只要不会被筛掉则一定是border。   那么我们卷完后只要枚举长度去看他的倍数有没有被筛掉就可以了。由调和级数,复杂度O(nlogn)。   LOJ过了,BZOJ上不出意外地T掉了。 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0