ntt

快速数论变换(NTT)

Deadly 提交于 2019-12-14 12:32:10
前置芝士: 快速傅立叶变换(FFT) 垃圾 \(FFT\) 我们已经知道 \(FFT\) 这个东西他很 \(nb\) 了,但是仍然存在很多局限性 比如说 \(1.\) 要用到复数,所以它很慢 \(2.\) 要用到复数,所以是 \(double\) 类型,有精度误差 \(3.\) 要用到复数,不能取模 \(……\) 我们发现就是这个垃圾复数拖了算法后退,要想办法摆脱它(´༎ຶД༎ຶ`)! 原根 聪明的珂学家们发现了一种奇妙的东西:原根 它可以代替复数进行变换,而且具有优良的性质 阶 若 \(gcd(a,p)==1\) ,且 \(p>1\) 则对于 \(a^x≡1(mod\ p)\) 最小的 \(x\) ,我们称为 \(a\) 的 \(p\) 的阶,记作 \(\delta _p(a)\) 相关定理 定理一 :若 \(p>1\) 且 \(gcd(a,p)==1\) 且 \(a^n≡1(mod\ p)\) ,则 \(\delta _p(a)|n\) 证明:根据定义理解一下吧…… 定理二 : \(\delta _p(a)|\phi(m)\) 证明:由欧拉定理: \(a^{\phi(p)}≡1(mod\ p)\) ,所以 \(\delta _p(a)≤\phi(p)\) ,根据定理一得到 \(\delta _p(a)|\phi(m)\) 原根 若 \(\delta _p(a)=\phi(p)\

FFT/NTT中档题总结

天大地大妈咪最大 提交于 2019-12-12 12:29:56
被DeepinC%怕了,把一些题放到这里来 T1Normal 其实这道题放到中档题也不太合适,个人感觉真的很难, 机房里好像都是颓的题解 因为期望的可加性,把每个点的贡献单独处理,即求期望深度 考虑$y$对$x$的贡献:当且仅当$x->y$的路径上第一个点就选$y$,$y$才能成为$x$的祖先 所以$y$对$x$的贡献就是:$P=\frac{1}{dis(x,y)+1}$,$E=1$ 所以最终答案就是$\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\frac{1}{dis(i,j)+1}$ 用点分治+$FFT$便可以$O(nlog_2^2(n))$解决 T2染色 题解在 二项式反演总结 里 T3城市规划 昨天推了一波式子,就被skyh和Deepinc狂%,但其实我的式子的组合数是错的 设$f[i]$代表$i$个点联通的方案数: 设$g[i]=2^{\frac{i*(i-1)}{2}}$ $f[i]=g[i]*\sum\limits_{j=1}^{i}C_{i-1}^{j-1}*f[j]*g[i-j]$ 便是一个裸的分治FFT了 来源: https://www.cnblogs.com/AthosD/p/12027865.html

「总结」多项式生成函数相关(1)

孤街浪徒 提交于 2019-12-11 20:19:02
实在是太毒瘤了。 大纲。 多项式生成函数相关 默认前置:微积分,各种数和各种反演,FFT,NTT,各种卷积,基本和式变换。 主要内容: 泰勒展开,级数求和,牛顿迭代,主定理。    //例题:在美妙的数学王国中畅游,礼物 多项式全家桶:乘法,求逆,求导,积分,分治,ln,exp,fwt,MTT。 //城市规划,图的价值,染色,遗失的答案,按位或,随机游走。 生成函数:普通型生成函数,指数型生成函数计数原理。 //猎人杀,遗忘的集合,生成树计数 例题。 一、泰勒展开和级数求和 1.泰勒展开 即对于任何函数 \(f(x)\) ,如果在 \(x_0\) 处 \(n\) 阶可导,那么满足如下公式: \[f(x)=\sum\limits_{i=0}^{n}\frac{f^{(i)}(x_0)(x-x_0)^i}{i!}\] 这里当 \(x_0\) 为0的时候被称作麦克劳林公式。 先推导麦克劳林公式 即: \[f(x)=\sum\limits_{i=0}^{n}\frac{f^{(i)}(0)x^i}{i!}\] 这里只证明多项式函数的正确性(其实是因为任意函数太难证了吧)。 设多项式函数: \[f(x)=\sum\limits_{i=0}^{n}a_ix^i\] 那么: \[f^{(i)}(x)=\sum\limits_{j=0}^{n}a_{j+i}x^{j}\prod\limits_{k

FFT/NTT基础题总结

柔情痞子 提交于 2019-12-11 09:01:09
在学各种数各种反演之前把以前做的$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$数组翻转后的数组 T2力 $f[i]=\sum_{j=1}^{i-1}\frac{q[j]}{(i-j)^2}-\sum_{j=i+1}^{n}\frac{q[j]}{(i-j)^2}$ $f[i]=\sum_{k=1}^{min(n-i,i-1)}\frac{q[j-k]-q[j+k]}{k^2}$ 构造出一个$g[i]=\frac{1}{i^2}$就是一个裸的卷积了 T3Normal 因为期望的可加性,把每个点的贡献单独处理,即求期望深度 考虑$y$对$x$的贡献:当且仅当$x->y$的路径上第一个点就选$y$,$y$才能成为$x$的祖先 所以$y$对$x$的贡献就是:$P=\frac{1}{dis(x,y)+1}$,$E=1$ 所以最终答案就是$\sum\limits_{i=1}^{n}

多项式全家桶

限于喜欢 提交于 2019-12-08 09:29:25
多项式全家桶(更新至快速幂) 开始爆肝多项式 1. FFT快速傅里叶变换 流程: 将多项式 \(\Theta (nlog_n)\) 转成点值表示形式 进行卷积, 再 \(\Theta (nlog_n)\) 转回来 离散傅里叶变换: 朴素转为点值, 需要将一个一个x带入, 而这里傅里叶搞到了几个可以优化的复数根 利用复数, 在复平面上画出一个单位圆, 将单位圆n等分, 每一个等分点为$\omega_n^i $, 接下来将 \(\omega^1_n \omega^2_n\cdots\omega^n_n\) n个根带入, 其中 \(\omega_n^i = cos(\frac{k}{n}2\pi) + i * sin(\frac{k}{n}2\pi)\) 稍等, 还要几个小性质才可以: 性质一: \(\omega^{2k}_{2n} = \omega_n^k\) 性质二: \(\omega_n^{k+\frac{n}{2}} = - \omega_n^k\) 接下来开始快速傅里叶变换: 设A(x) = \(a_0 + a_1x + a_2x^2 + \cdots + a_{n-1}x^{n-1}\) 利用分治, 将A按x的指数分为奇偶两部分 \(A(x)=(a_0+a_2x^2+\cdots + a_{n-2}x^{n-2})+(a_1x+a_3x^3+\cdots\) $ a_{n-1

Implementing FFT over finite fields

冷暖自知 提交于 2019-12-06 23:52:04
问题 I would like to implement multiplication of polynomials using NTT. I followed Number-theoretic transform (integer DFT) and it seems to work. Now I would like to implement multiplication of polynomials over finite fields Z_p[x] where p is arbitrary prime number. Does it changes anything that the coefficients are now bounded by p , compared to the former unbounded case? In particular, original NTT required to find prime number N as the working modulus that is larger than (magnitude of largest

【模板】多项式全家桶

淺唱寂寞╮ 提交于 2019-12-06 12:46:53
超好写的 #include<stdio.h> #define inf 998244353 #define I 86583718 #define MAXN 8388608 char buf[1<<20],*p1,*p2; #define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++) inline int R(){ char t=GC; int x=0; while(t<'!')t=GC; while(t>='!')x=x*10+t-48,t=GC; return x; } int _0[MAXN],_lset=-1,inv[MAXN],tmp[MAXN]; inline void init(){ inv[1]=1; for(int i=2;i<MAXN;i++)inv[i]=inf-1ull*inv[inf%i]*(inf/i)%inf; } inline void mod(int &p){p>=inf?(p-=inf):0;} inline int getinv(int p){return p<3e6+5?inv[p]:inf-1ull*getinv(inf%p)*(inf/p)%inf;} inline int ksm(long long a,int b){int ans=1;while(b)

【学习笔记】二项式反演

蹲街弑〆低调 提交于 2019-12-06 07:37:25
考场上的我猜测到了某个题是二项式反演 可惜我不会啊 分治NTT给了60的暴力 然而他们的分治NTT都能跑1e6/dk 回归正题 二项式反演大概就是关于二项式的反演 (废话) 一般来说 初始状态都是状压的0/1状态 然后它们有很好的性质 与具体哪一位的状态无关 所以可以直接记录1的个数 又因为反演≈容斥 所以它的两个基本形式就很好看了 $f(n) = \sum_0 ^ n (-1)^i \binom{n}{i} g(i) \Leftrightarrow g(n) = \sum_0 ^n (-1)^i \binom{n}{i} f(n)$ 一般这个柿子用不到(吧 因为很少上来就是个容斥形式 $f(n) = \sum _{i=0} ^n \binom{n}{i} g(i) \Leftrightarrow\sum_{i=0}^n (-1)^{n-i} \binom{n}{i} f(i)$ 一般是这个柿子比较有用qwq 具体证明自行百度吧(~~其实就是我懒~~ 例题 [HAOI2016] 染色 其实这个题完全可以不用二项式反演直接容斥 也间接性证明了反演的本质就是容斥 考虑恰好为S有k个的限制 按照套路转化为至少有k个为S 设所求函数为G(x) 容斥函数为F(x) 容斥函数可直接计算$F(x) = \binom{m}{x} (m-i)^{n-ix} \frac{(sx)!}{(x!)^s

牛客 17439:Endless Pallet

China☆狼群 提交于 2019-12-06 03:16:39
题目传送门 算法:min-max 容斥、树上背包、NTT。 题意简述 有一棵 \(n\) 个点的树。一开始所有点都是白色,每次操作会随机选择 \(\frac{n \times (n + 1)}{2}\) 条路径中的一条,将路径上所有点染黑。求所有点都被染黑的期望操作数。 \(n \le 50\) 。多组数据。对 \(998, 244, 353\) 取模。 题解 套路性地,我们使用 min-max 容斥。 \[ \begin{aligned}E(\max(U)) &= \sum_{\phi \neq S \subset U} (-1) ^ {\lvert S \rvert - 1} E(\min(S)) \\ &= \sum_{\phi \neq S \subset U} (-1) ^ {\lvert S \rvert - 1} \frac{1}{P(路径经过\ S\ 内的点)} \\ &= \sum_{\phi \neq S \subset U} (-1) ^ {\lvert S \rvert - 1} \frac{1}{1 - P(路径不经过\ S\ 内的点)}\end{aligned} \] 如果我们把树画出来,并将 \(S\) 内的点标记,可以发现,这些点把原树分成了若干个连通块,而每个连通块内部可以任意选取路径,能够保证该路径不经过 \(S\) 内的点。而一旦路径跨越连通块

多项式全家桶

假如想象 提交于 2019-12-05 14:41:38
多项式乘法 多项式求逆 多项式除法/取模 多项式求导 多项式多点求值 多项式快速插值 code: #include <bits/stdc++.h> #define ll long long #define ull unsigned long long #define setIO(s) freopen(s".in","r",stdin) // , freopen(s".out","w",stdout) using namespace std; char buf[100000],*p1,*p2; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char s=nc(); while(s<'0') s=nc(); while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc(); return x; } void print(int x) {if(x>=10) print(x/10);putchar(x%10+'0');} const int G=3; const int N=2000005; const int mod=998244353; int A[N],B[N],w[2][N],mem[N*100],*ptr