数论大杂烩

数论大杂烩

Latex渲染方式使用SVG可避免出现迷之竖线(如果SVG无法显示,还是换回去吧

定义:

元函数:e(n)=[n=1]
恒等函数:I(n)=1(为什么叫恒等函数呢…明明是恒1函数)
单位函数:id(n)=n
欧拉函数:φ(n)=ni=1[gcd(n,i)=1],比n小且与n互质的数的个数
约数个数函数:τ(n)d(n)τ(n)=dn1
约数和函数:σ(n)=dnd
莫比乌斯函数:μ(n)= 传送门


证明:m%n=d(a%b)ad=m  ,  bd=n

其实很简单:m%n=mmnn=adadbdbd=d(aabb)=d(a%b)


证明:ni=1[(n,i)=1]i=nφ(n)+[n=1]2

感知正确性:因为in 互质,所以nin 也互质(反证法即可,假设gcd(ni,n)=d,则didn,矛盾)。所以ni=1[(n,i)=1]=2ni=1[(n,i)=1]in(两两配对即可)。把2n移动到等式左边即可。
从左到右的过程如下:
ni=1[gcd(n,i)=1]ini=1dgcd(i,n)μ(d)idnμ(d)diidnμ(d)ndi=1iddnμ(d)(d+n)nd2dnμ(d)(n+nnd2)ndnμ(d)nd+ndnμ(d)2nφ(n)+n[n==1]2Q.E.D


证明:τ(mn)=injm[gcd(i,j)=1]

证法1:
对于任意一对i,j(i|nj|m)imjmn的约数,设d=gcd(i,j)i=daj=db

  • 如果d1,那么imj=damdb=amb,其中ab互质。因此任意一对i,jgcd(i,j)1,都可以被另一对ijgcd(i,j)=1唯一代替
  • 如果d=1,对答案贡献1*/

证法2:
先考虑一个质数的情况,假设m=pk1n=pk2,那么显然因数应该有p0,p,p2,,pk1+k2k1+k2+1个。
对指数k[0,k1+k2+1]的取值,建立一个二元组映射:{(pk,1)k[0,k1](1,pkk1)k(k1,k1+k2],可以发现,每一个这样的二元组表示法,都能与一个\sum_{i|p^{k_1}} \sum_{j|p^{k_2}}相对应,因此对于一个质数的情况成立

考虑合数的情况,其实就是将很多质数相乘。对于每一个质数,都写成一个二元组表示形式,再在每个质数的二元组中选出某一项相乘,那么最后得到的二元组(x,y)中,xy也是互质的,因此也能和\sum_{i|n} \sum_{j|m}相对应。并且这个选择过程,实际上就是给每个质因子钦定了指数,因此每一种选择方案都是一个因数。因此上式相等

那么上式成立,证毕。例题:BZOJ3994


证明:σ(mn)=injmimj[gcd(i,j)=1]

证明同上

补充:ai=1bj=1ck=1τ(ijk)=gcd(i,j)=gcd(i,k)=gcd(j,k)=1aibjck

据说这个等式的名字叫:「陈老师r老师恒等式」。
可以用上面的证法2进行推广得到


证明:nij=nij

并不知道为什么大家都说这很显然…
证法1:右式=nijk=nijk=左式,证毕。
证法2:
设左式值为k,则ni=kj+r1,其中r1<j,继续替换得到n=i(kj+r1)+r2=ijk+r1i+r2,其中r2<i。设右式值为k,类似替换可以得到n=ijk+r,其中r<ij。因为r1i+r2<r1i+iji,因此对左式和右式的分解可看作是将两边同时除以ijkk为商,r1i+r2r为余数。由以上已知,商和余数唯一确定,因此k=k,两式值相等,证毕。该证明方式来源于ADP+Pi==ATP


理解:(x+y)n=ni=0 Cin xi yni

(貌似是二项式定理…?)
(x+y)n拆开写成(x+y)(x+y)(x+y),从每个括号里选一项出来的乘积之和,就是这个式子的值(平时手算多项式乘法的时候,就是每个括号里取一项相承)。假设选了ix,那么就会选niy,选择方案一共有Cin种。把选了i[0,n]个x,对所有方案数求和,与左式等价,用式子表达出来就是ni=0 Cin xi yni


证明:dnμ(d)=[n=1]

(这个式子的卷积形式是:μ×I=e
根据定义,只有不包含平方因子的数μ才不为0,因此只考虑这些数
那么考虑只有互异因子的数的贡献(假设质因子个数为k):
只有0个互异因子的数(其实就只有1):(+1)C0k
有1个互异因子的数:(1)C1k

求和得到sum=C0kC1k+C2k+(1)kCkk
由二项式定理易知,当k不为0时:sum=(1+(1))k=0。特殊的,k0时,sum=1


理解:dnφ(d)=n

(这个式子的卷积形式是:φ×I=id
方法1:对于数字i(i[1,n]),写成in的形式并化为最简分数kd,发现所有以d为分母的分数个数就是φ(d),所以dnφ(d)=n
方法2:利用φ(n)=d|nμ(d)nd,那么有dnφ(d)=dndgndμ(g)=n(只有当nd为1的时候,gndμ(g)才为1,此时dn


Tricks:ni=1niφ(i)=ni=1i

这个式子,咱们倒着推…
ni=1ini=1kiφ(k)nk=1nkiφ(k)nk=1nkφ(k)
简直有毒这个!上面这个推导过程 还是很眼熟的,然而倒着来me就shabi了,例题BZOJ4173


理解:φ(n)=d|nμ(d)nd=ikij=0μ(pji)pkij=ipki1i(pi1)=ni(11pi)

(第一个式子到第二个式子,感知正确性:由id(n)=φ×I,由题φ(n)=μ×id=μ×φ×I=e×φ=φ )

由定义,φ(n) 表示[1,n]中与n互质的数的个数。如果p1n的质因数,那么p1,2p1,3p1...kp1(kp1n)n都不互质,因此减去这些数字的个数,共计np1个。但是像p1p2这样的数字会被减去两遍,因此需要加上 p1p2 ,2p1p2 ,3p1p2...这些数字的个数,共计np1p2个。根据 μ的定义,上面的每项恰好对应了相应的系数,所以φ(n)=d|nμ(d)nd成立。ikij=0μ(pji)pkij是把n分解了之后的式子,因为φ有积性,所以提取出每个因数幂单独求φ再乘起来就好了。注意到只有在j0或者1的时候μ(pji)才不为0,因此可以继续化简到后面的式子。然后,把每个括号里都提一个pi出来,于是式子变成了ipkii(11pi),拆开写就可以得到最后的式子。(最后的式子貌似手推常用)


理解:ni=1d|ink=1nkd=1

左半边的含义是:枚举每个i(i[1,n]),然后去枚举它的约数
右半边的含义是:对于每一对(i,d)满足i[1,n]di,设k=id 。枚举倍数k,然后枚举当前倍数下的d有哪些
两边换了枚举顺序,但是枚举的东西是一样的,两式等价
这种思想在推导过程中十分常见


理解:S(n,m)=1m!mk=0(1)k(mk)(mk)n

这是斯特林数的单个求法,求解一个斯特林数Θ(n)(貌似这个是卷积形式,于是求一行可以优化到Θ(nlog2n),不过me不会)
考虑斯特林数的含义,把n个数拆成m个集合的方案数,也可以是「把n个不同的小球放进m个相同的盒子(盒子非空)的方案数」。另外,显然的「把n个不同小球放进m个不同的盒子」的方案数是mn
考虑容斥,先把盒子看作是不同的。枚举有k个盒子为空,容斥系数为(1)k,这k个空盒子是从m个盒子中选出来的,即(mk),然后把n个球放进mk个非空盒子中,方案数是(mk)n。容斥之后可以得到「n个小球放进m个不同盒子(盒子非空)」的方案数(至少0个为空-至少一个为空+至少两个为空…这样)。最后我们使盒子变得相同,于是乘上一个1m!来消序


理解:mi=1S(n,i)P(m,i)=mn

这个式子的意思是:现在有n个小球,m个盒子,盒子互不相同,且球也互不相同,允许盒子为空的情况下,把小球装进盒子的方案数 等于nm

首先,把n个不同的小球装进m个无区别的盒子,且盒子不允许留空的方案数,也就是斯特林数S(n,m),这个可以递推求得(S(n,m)=S(n1,m1)+mS(n1,m),新的球自成一组,或者是放进原来的某一组)

在这个基础上,我们允许盒子留空,那么只需要枚举有多少个盒子不为空即可。方案数为mi=1S(n,i)

然后,我们再给盒子编号,此时,留空的盒子有编号,并且没有留空的盒子还是有编号。对于留空的盒子,相当于是从m个盒子中选出m-i个留空,方案数是C(m,mi)=C(m,i),而对于没有留空的盒子,因为有了编号,所以需要乘上一个阶乘,方案数是i!(举个栗子:盒子没有编号的时候{{1},{2},{3}}和{{2},{1},{3}}是一样的,而盒子有了编号{{1},{2},{3}}和{{2},{1},{3}}就不一样了)。于是方案数就是mi=1S(n,i)C(m,i)i!,即mi=1S(n,i)P(m,i)

我们把mn拆开成:(1+1+...+1)n,显然这就是把n个球放入m个有区别的盒子的方案数(回忆一下手算多项式乘法,每个括号里取一项相乘,在这里每个括号里都选择了一个1,也就是选择把球放入一个盒子)


推导:ni=1mj=1(i,j)=min(n,m)i=1φ(i)nimi(gcd( i , j )简写为( i , j ))

下面假设有 mn
ni=1mj=1(i,j)md=1dni=1mj=1[(i,j)==d]md=1dndi=1mdj=1[(i,j)==1]md=1dndi=1mdj=1ki,jμ(k)md=1dmdk=1μ(k)ndkimdkj1md=1dmdk=1μ(k)ndkmdk
T=dk,上式确定了 dk,从而确定 T。下面我们先确定Td
mT=1nTmTdTdμ(Td)mT=1nTmTφ(T)


二次剩余

ZJQQQAQ
MISKCOO
me的理解:x2n(modp),这其实就是模意义下,给n开根
其实这个方法比较有意思,me只知道正确性,而不知道如何得出的这个方法…
me目前只会p是奇质数时的求解方法,不过还是mark一下吧
(如果没有声明,下文全在模p意义下)

首先要知道欧拉准则(专门用于判断给定整数是否是某一质数的二次剩余)

  • 由费马小定理:xp11(modp),所以(x2)p121(modp),即np121(modp)。这个逆过来就是欧拉准则:如果np121(modp),那么就无解。

我们需要找到一个a,满足a2n没有解(随机找,找到就break)。我们记w=a2n,那么一个合法的x就是(a+w)p+12,证明如下:

  • 随机的期望次数是2,因为「在[0,p1]范围内,有解的np12个(n0) 」

    • 这里从x入手,如果有两个数u,v[1,p1],满足u2v2(modp),那么显然有p(u2v2),又因为(u2v2)=(u+v)(uv),而(uv)一定小于p,无法成为p的倍数,因此一定有p(u+v)。这个定理逆过来也是成立的,也就是说,如果两个数它们的和为p,当且仅当这两个数满足u2v2(modp)。于是不同的平方数有p12个,这些平方数也就是「有解的n
  • 还有这个式子:wpw(modp)

    • wpww(p1)ww2p12w(a2n)p12w(1)=w
  • (a+b)p=ap+bp(modp)

    • 用二项式定理把左边拆开,发现组合数阶乘里都有p,就被模掉了,最后只剩下ap+bp

那么有下面的推导:
((a+w)p+12)2(a+w)p+1
(a+w)(a+w)p
(a+w)(ap+wp)
(a+w)(aw)(由费马小定理和上面的第二个式子)
a2w
n
然后发现它确实就是一个解=w=
至于这个w呢,因为w在实数域上其实不存在,那么我们可以类比1去定义一个虚数域,可以证明这是一个合法的数域(czy的博客里有写到)。于是实际操作的时候定义一个struct,然后像虚数一样的运算。

cpx operator * ( const cpx &A , const cpx &B ){
    cpx rt ;
    rt.R = ( A.R * B.R %mmod + A.I * B.I %mmod * w %mmod ) %mmod ;
    rt.I = ( A.I * B.R %mmod + A.R * B.I %mmod ) %mmod ;
    return rt ;
}

找到一个合法的a之后,就定义(cpx){a,1} 然后快速幂即可,最后的虚部一定为0(虽然不知道为什么,但是模拟的数据确实是这样),实部就是解。
UPD:为什么虚部一定为0呢?由拉格朗日定理,一个n次的多项式在模p的数域下最多有n个根(让f(x)0的解称为根)。而我们现在的虚数域,是在原来的模p域上扩展的,所以如果模域有解,那么这个解在扩展域中同样生效。并且我们已知的是,每一个二次剩余都有两个解,并且二次剩余是个二次多项式。所以扩展域上的解也一定是原来模域的解,所以虚部为0。czy的博客里有更详细的说明,可以去看看

一个小性质

如果n是模p的二次剩余,即x,x2n(modp),那么对于p的任意元根g,有gbn,b
证明如下:
对于某一元根g1,假设g1ax(modp),那么g12an(modp)
假设有另一元根g2,使得g2bn(modp)且b为奇数,假设g2cg1(modp)
那么(g2c)2an(modp),易知2acb(modp1),与假设矛盾(左边是偶数右边是奇数)
证毕。



拉格朗日乘子法

知乎 - 如何理解拉格朗日乘子法
求解多元方程f(x,y)在限定条件g(x,y)a=0下的极值
可令新函数L(x,y,λ)=f(x,y)+λ(g(x,y)a)=0,然后对x,y分别求偏导数,要求所有偏导数为0,解出来的位置就是一个极值

这是为什么呢…me觉得这简直太神了
首先,一个多元函数要有极值,必要条件是,偏导数都是0。(大概脑补一下,把偏导数看作斜率的话,偏导数都是0就是说不论向着哪个方向走都是一样的平(各个偏导数合起来貌似就是多维梯度?)。如果有一维不是0,那肯定可以朝着斜率为正的方向走,可以得到更大的值)

然而这里有了g(x,y)a=0这个限制,就相当于是在高维的空间里强行划定一根线当作界限(图片摘自上面那个问题[戏言玩家]的回答,图片不是me的,侵删),可以直观的感觉到,是在相切的时候取到极值
!这里写图片描述

那么两条曲线相切,意味着在切点位置的法向量平行,也就是向量的比值为常数,设这个常数为λ,于是f(x,y)=λg(x,y),移项,然后把常数放进去,得到(f(x,y)+λg(x,y))=0,这实际上就是对新函数L(x,y,λ)=f(x,y)+λg(x,y)取各维偏导数,并且值为0,那么就变成了L(x,y,λ)的极值

再反过来看,L(x,y,λ)取极值的时候,要求各个偏导为0,当对λ取偏导的时候,实际上就要求g(x,y)a=0,然后关于g的一项就没有了,所以极值的时候L也恰好等于f

补充:曲线的法向量

在曲线的某一点求法向量,就是先求出对于那个点的切线,然后法向量垂直于切线
圆的法向量比较显然,就是该点与圆心连线上的向量,方向随意
那么对于曲线呢,可以取出很小很小的一段,然后把那一段近似成圆

补充:偏导数

对某一个维度单独求导,只保留关于这个变量的导数,而把其它变量看作常数。比如f(x)=x2+y2,关于x的偏导就是fx=2x+0。这相当于只看一个维度的变化情况



FWT·FMT

关于这些Fast xxx Transform啊,其实不要把它看得太复杂了,它就是一个分治算法而已,用来优化卷积的

朴素的卷积运算是O(n2)的,复杂度太高,需要被调教

所以寻思着,构造一个变换T,并且这个变换还要有三个性质:

  • 正变换算的快
  • 存在逆变换,并且逆变换也要算的快
  • 能够从T(A)T(B)快速得到T(C)

于是可以先快速的算出两个数组的正变换。然后快速的得出「目标数组」的正变换。最后再快速的把「目标数组」还原,然后这个问题就被解决了
这个「快速的」,要求不高,只要最后比O(n2)好,那么优化的目的就达到了

用FWT「与」运算来举个栗子

符号表示与,其余符号为数字运算符号,A,B,C分别是三个数组(或者向量):

要计算Ck=ni=0nj=0 [ij=k] aibj

首先呢,注意到 (ik=k) and (jk=k)(ij)k=k

所以利用这个性质,尝试构造一个变换T,并且这个变换还要有三个性质:

  • 正变换算的快
  • 存在逆变换,并且逆变换也要算的快
  • 能够从T(A)T(B)快速得到T(C)

    然后就想出来了一个这样的变换:设A变换得到的数组是a,那么ai=nj=0[ji=i]Aj

    这个变换它有什么用呢?
    首先呢,这个正变换可以「按位分治」计算,复杂度是O(nlog)
    然后呢,这个变换的逆变换,也可以「按位分治」计算,复杂度还是O(nlog)
    最后呢,发现ci=aibi,也就是「可以从T(A)T(B)快速得到T(C)」,复杂度是O(n)
    显然总复杂度比O(n2)优秀,好,优化的目的就达到了!

    关于FWT「异或」变换

    用于处理异或的变换是这么定义的:
    定义运算a×b为,a按位与上b之后,1的个数的奇偶性
    变换:ai=nj=0[i×j=0]Aj[i×j=1]Aj
    为什么要这么构造呢?me也不知道。不过JCY说,这是由于+1,1的加减与异或类似,(1)+(+1)都是1,而+(1)(+1)都是1

    然后这个变换的 正变换(0=0+1,1=01)和逆变换(0=0+12,1=012) 都是可以快速求得的
    然后由于(i×k)(j×k)=(ij)×k,所以可以由T(A)T(B)算出T(C)
    感觉很神奇

    对FWT的一些补充

    关于实现:
    首先把数组长度补到2的次幂,这样的话在写的时候就会方便很多,不需要特判边界
    然后正变换还是很简单的,递归和非递归的写法都比较清晰
    但是逆变换就不清真了,看了网上一些大佬的实现,发现写出来的和推出来的式子不太一样……不过大同小异

    因为位运算是独立的,所以无论是正变换还是逆变换,都只需要按位考虑贡献,而考虑贡献的顺序是不影响的。
    比如「与」卷积的逆变换:
    假如说现在有一个变换之后的00000,那么这里面包含了从00000~11111所有的东西。
    那么一位一位的减,00000 - 1xxxx - 01xxx - 001xx - 0001x - 00001,得到的就是00000本身的值了
    然而也可以换个顺序减:00000 - xxxx1 - xxx10 - xx100 - x1000 - 10000,效果与上面是一样的
    正变换的顺序其实也可以类似的改变
    所以一般实现的时候,为了能把代码写短一点,正变换和逆变换采用同种顺序
    如果正变换从低到高,那么逆变换也是从低到高,这样就可以把两个变换压到一个函数里面……

    FWT的变换是一个线性变换
    什么是线性变换,me也说不清楚。JCY:就是可以把正变换和逆变换看成右乘了一个矩阵
    然而me还是不懂这有什么用……不过me觉得me还是get到了一点东西

    因为FWT整个正变换的过程,只用到了加减运算,而加减运算是可以随便叠加的,所以有一些很优美的性质
    比如说,和的变换 等于 变换的和:T(A+B)=T(A)+T(B)
    再比如说,可以边运算边取模(但是异或FWT有个除2,不知道可不可以用乘逆元的方法解决)
    有了这个性质,就可以去做一些题,比如:[UOJ#310]黎明前的巧克力

    关于FMT的一道论文题

    [HAOI2015]按位或 传送门
    me的天哪…me看这道题看了一晚上???
    这道题主要还是用到了一个性质:变换的和等于和的变换
    这样的话,一个很难求和的东西,如果它的变换很好求和(有性质的支撑),那么我们就可以先变换,求和,然后再变换回去
    卧槽这么简单的道理,me特喵的为什么看了一晚上???

    ACyume-集合卷积学习
    neither_nor-FWT
    tmkkkkk-快速沃尔什变换(FWT) 学习笔记


    FFT·NTT

    这里主要是《再探快速傅立叶变换-毛啸》的笔记,此处整理了自己的理解

    Part-1 原理解释

    1.1:    cr=p,q[(p+q)modn=r]apbq
    与原式等价,这里的n是一个大于c的长度的2的整数次幂的数字。这样的话,取模下来就不会发生混叠(就是说不会真的被模掉,所有的p+q本来就小于n)。

    1.2:    1nn1k=0ωvk=[vmodn=0]
    ω是一个复数,这个复数满足ωn=1,并且n是最小的能让ω变成1的幂指数)
    这个式子呢,首先n是个偶数,所以可以把它拆开写,然后两两配对,像这样:1n(ω0+ωv+ω2v++ω(n1)v),其中ωvω(n1)v是相反数(因为ωn是1,所以ω(n1)v相当于是ωv,按照虚数的运算,这两个确实是相反数)。然后ω0ωn2v是相反数,所以上式得证


    然后接下来,论文里就把 式1.1 里面的判断句换成了 式1.2,然后有了这个:
    cr=p,q[(p+q)modn=r]apbqcr=1nn1k=0ωrkpωpkapqωqkbq我们把这个式子右边换一换,定义一个多项式A(x)=n1k=0akxk,那么于是我们就可以用多项式的形式来改写这个式子:cr=1nC(ωr)。其中C(x)=n1k=0ckxk,里面那个ck,就是A(ωk)B(ωk)

    由上,我们得到了一个新的求数列C的方法:

    • 对于所有的 ωk  (k[0,n1]),求得多项式A(x)=An1k=0akxkB(x)=Bn1k=0bkxk在带入各个ω时的值,我们把这一堆数字叫做点值表达式

      • 把点值表达式对应相乘,得到多项式C(x)各项的系数
      • C(x)求点值,求出来的点值就对应着待求的C(x)的系数,也就是最开始那个卷积的结果
      • 这个过程基本符合me上面概括的那种Fast xxx Transform的思路,接下来要干的事情,就是寻找一种快速的方式,来带入未知数运算点值

        Part-2 寻找快速算法

        定义一种写法ωkn,表示:这是一个「最小的能让ωx=1的数字是n」这样的ω,这个ωk次方写作ωkn
        我们发现ω其实是有很多性质的,比如说ωn2n=1,再比如说ω2m2n=ωmn

        尝试着利用这些性质去加速运算
        我们直接批量的带入未知数,一次性算完所有的点值
        A0(x)A(x)的偶次项之和,A1(x)A(x)的奇次项之和(注意,这里的A,A0,A1都是多项式),再令mn2,那么有:
             A(ωmn)=A0((ωmn)2)+ωmnA1((ωmn)2)A0(ωmn/2)+ωmnA1(ωmn/2)A(ωm+n2n)=A0((ωmn)2)ωmnA1((ωmn)2)A0(ωmn/2)ωmnA1(ωmn/2)
        这时候惊奇的发现!对于一对未知数ωmnωm+n2n,要求此时的点值,我们只需要算A0(ωmn/2)A1(ωmn/2)这两个东西就可以了,而且它们的单位根从ωn变到了ωn/2。这样,只需要往下走log层,这个单位根就会变成1,并且多项式也只剩下了一项,那么这个多项式的值就是对应的系数的值,这就是递归边界了

        于是我们完成了:1.正变换算的快;2.存在逆变换,逆变换也算的快;3.可以从已知项的变换,快速推得未知项的变换;
        那么这个Fast xxx Transform就大功告成了

        Part-3 任意长度的DFT

        哇天哪…为什么me读论文就这么困难呢…..?!
        啃论文的时候,建议结合这个食用outer_form’s POJ2821

        先说一说循环卷积
        最开始的时候,我们有这个式子cr=p,q[(p+q)modn=r]apbq
        我们说n是一个比c的长度大的,2的整数次幂的数。如果nlenc,那么p+q就会真的被取模,从而使原来应该在n+δ项上的值,累加到了δ项上面,这样就会发生信息混叠。试想一下,数学上解直线,需要带入两个点;解二次函数需要三个点…那么解k次函数就需要k+1个点。而现在nlenc,按照前面的想法,显然是无法准确解出原来的系数的(因为信息已经混叠了,而且无法还原(要还原只能枚举)。音频里,取样率低了之后音质就会有损,也是这个道理)

        但是有些题,就是要让我们去算这个循环卷积,那有些什么办法呢?
        最暴力的,循环卷积就是把高的累加到低的上面来,那我们可以先FFT一次得到c,然后把cn+k累加到ck上来
        然而这样效率比较慢,尤其是要在循环卷积意义下快速幂的时候,我们就只能一次一次的卷了…
        (参见SDOI2015序列统计,这就是一道循环卷积快速幂的题)
        为什么只能一次一次的卷呢?因为我们正常DFT是带入了ω0ωn1n个点去求值,也就是说,自带了一个循环长度为n的意义,如果我们直接在DFT之后的数组上快速幂然后再IDFT回去,最后只能得到长度为n的循环卷积。如果题目要求的循环长度不是2的整数次幂,除了快速幂一次一次卷之外,别无他法

        而我们更希望,可以直接在DFT之后的点值上进行操作
        函数加,对应的点值也加,函数乘,对应的点值也乘。对函数(多项式)操作是很麻烦的,但对点值操作明显轻松的多
        于是就有了下面这个东西

        Bluestein’s Algorithm
        这个方法的名字叫Bluestein’s Algorithm,它使用一次FFT,来实现任意长度的DFT(又叫CZT)
        因此实际上做完整个算法需要3*3=9次DFT(因为一次CZT = 一次FFT = 三次DFT,总共三次CZT)

        它是这样的,我们在求点值的时候,用的是这个式子(记这个点值为a,而多项式里系数为b):
        am=A(ωm)=n1k=0ωmkbk然后我们尝试把这个东西转化成卷积:
        n1k=0ωm2+k2(mk)22bkωm22n1k=0ω(mk)22ωk22bk发现这其实已经是一坨类似卷积的形式,我们用Bi来代换ω(in)22,用Ci来代换ωi22bi。于是得到下式:
        ωm22n1k=0Bm+nkCk然而它的上界仍然是n1,需要找到一种方法,使得上界变为n+m来满足卷积形式
        我们发现,这个系数数组是给出了的,bk中只有k[0,n1]才有值,而其余的bk都是0。根据这一性质,我们就可以直接把上界扩展到n+m,然后变成了这样:
        ωm22n+mk=0Bm+nkCk
        至此,上面的CZT已经被完全转化成了一个卷积形式。
        具体的实现呢?me yy的不保证正确性可以先处理出B和C数组,然后做一遍FFT,算出后面那个卷积式。然后把卷积得到的第n+δ   (δ[0,n1])项取出来,乘一个ωδ22,这些就是我们想要的点值了///

        关于这个ωi22这个分数啊,如果i是个奇数的话,那么指数就会出现0.5,这相当于对ω进行了开根,然而ω12n有两个解:ω12nωn+12n,那么应该取什么才对呢?

        其实可以这么想,因为上面ωm22,ω(mk)22,ωk22这三项要么是三个全是偶数,要么是两奇一偶,所以最终的结果是不存在那个小数的,所以我们只需要保证,最后的结果不存在那个小数就可以了。所以,为了方便,不如都选第一种开根方式,这样下来最后的结果也是合法的

        Part-4 一些题

        这部分就略过了。。。
        反正就是多项式乘法优化其他算法(特指DPhhhhh)
        小技巧,比如说挪动范围啊,翻转匹配什么的

        Part-5 FFT的常数优化

        这上面讲的还不错,可以去看看:水郁-拆系数FFT
        (tips:因为DFT和IDFT其实是一样的,所以下文统计DFT次数时,是一起计算的)

        计算:A(x)=B(x)C(x)+D(x)E(x)
        首先,一个简单粗暴的方法就是,直接算B(x)C(x)D(x)E(x),然后再把它们俩加起来…这样 一共需要6次DFT
        我们回归本质的去理解这个式子。B(x)C(x)都是多项式,在计算B(x)C(x)的时候,实际上是求得了这两个多项式在一些特殊点(对,就是ω)的取值,然后再用这些取值倒推回去。
        那么我们明显不用「算一个就立刻倒推一个」,我们可以算完一起倒推回去。就是说,把B(x),C(x),D(x),E(x)分别DFT之后得到b,c,d,e,然后令ak=bkck+dkek,然后统一IDFT,这样就直接得到A(x)了。这种方法需要5次DFT

        虽然从数字上来看,效率差不多,但是这里利用的就是点值加和点值乘,思想还是很重要的

        计算:A(x)=B(x)C(x)的第n2到第3n2(假设B和C都是长度n)
        对于这个式子,我们平时操作,肯定是扩展到2n,然后FFT一次
        然而它只要中间的部分,我们只需要保证这一部分不发生混叠就好了,于是我们可以只扩展到3n2

        (对没错!这就是一个常数优化)

        小范围暴力
        这个就更玄学了... FFT常数实在是太大了!数据范围小的时候甚至跑不过暴力!
        所以在用到「常数很大的分治算法(比如分治FFT)」的题当中,如果当前区间太小,直接暴力搞就好了…

        乘法次数的优化
        快速幂一定是最优的吗?可以去看一看一个知乎,与这个问题没有直接关系:如何用最少的操作打出N个1
        要凑出一个数,其实快速幂真的不够优秀,只是保证乘法次数不超过2logn而已(那个2,把快速幂写出来就知道了)
        而这个复杂度对于「求出多项式的幂 」这样的任务,有点大了
        我们使用一种黑科技叫addition chain,这是一条计算数字的链,保证相邻数字之差都在链上出现过,这样我们就可以记忆化每个步骤来加速运算。
        举个例子,对于数字6,我们使用快速幂达到之,是这样的124,然后在2和4的时候分别乘一下,总运算次数是4
        而这样计算:1246,其中2=1+14=2+26=4+2,我们只计算了三次,这样显然要优秀一些
        然而求解addition~chain是NPH的,我们只能用BFS去找近似解,不过效果还是很不错的

        还有一个啥?Method~of~Four~Russians?看不懂看不懂,求讲解qwq

        Part-6 FFT的技巧——合并

        (下面,F(x)是指一个多项式,当x为一个确定的值时,F(x)是一个值。另外f_k是值第k项系数)
        假设我们现在要对两个实数多项式A(x)B(x)分别进行DFT,假设nA,B的长度,且已经被调整至一个2的整数次幂
        我们如此构造一个多项式:
        P(x)=A(x)+iB(x)\\Q(x)=A(x)-iB(x)我们来看一下PQ有什么关系。设F_p[k]表示P在DFT之后得到的序列的第k项,F_q[k]同理
        即:F_p[k]=P(\omega_n^k),F_q[k]=Q(\omega_n^k)

        然后开始一系列的推导(使用X来代替\frac{2\pi jk}{2n})
        \begin{align*} F_p[k] & =A(\omega_{2n}^k)+iB(\omega_{2n}^k)\\ & = \sum_{j=0}^{n-1}(a_j+ib_j)\omega_{2n}^{jk}\\ & = \sum_{j=0}^{n-1}(a_j+ib_j)(\cos X+i\sin X) \end{align*}

        \begin{align*} F_q[k] & =A(\omega_{2n}^k)-iB(\omega_{2n}^k)\\ & = \sum_{j=0}^{n-1}(a_j-ib_j)(\cos X+i\sin X)\\ & = \sum_{j=0}^{n-1}(a_j\cos X+b_j\sin X)+i(a_j\sin X - b_j\cos X)\\ & = conj\left( \sum_{j=0}^{n-1}( a_j\cos X + b_j\sin X ) - i( a_j\sin X - b_j\cos X ) \right)\\ & = conj\left( \sum_{j=0}^{n-1} a_j(\cos X - i\sin X) + b_j( i\cos X + \sin X) \right) \\ & = conj\left( \sum_{j=0}^{n-1} a_j\big( \cos(-X) + i\sin(-X) \big) +ib_j\big( \cos(-X) + i\sin(-X) \big) \right)\\ & = conj\left( \sum_{j=0}^{n-1} (a_j+ib_j)\big(\cos(-X)+i\sin(-X)\big)\right)\\ & = conj\left( \sum_{j=0}^{n-1} (a_j+ib_j)\omega_{2n}^{2n-jk}\right)\\ & = conj( F_p[2n-k] ) \end{align*}
        这提示我们,我们只需要一次DFT,就可以同时计算出F_p[]F_q[],然后,我们就可以通过
        \begin{align*} DFT(A[k])&=\frac{F_p[k]+F_q[k]}{2}\\ DFT(B[k])&=-i\frac{F_p[k]-F_q[k]}{2}(注意这里必须要有个负号) \end{align*}完成对两个数组的DFT的计算

        这个推导简直神炸了!!!

        Part-7 FFT的技巧——任意模数卷积

        对于这个东西,我们已经有一种比较成熟的通用解法,就是3模数NTT,然后用中国剩余定理合并
        当系数的大小在10^9级别时,卷积之后数字大小在10^{23}级别左右,所以必须要3个巨大的模数搞一搞
        这样的话,我们一共要进行9次DFT

        不过这里有一种新方法——
        首先,还是一样的假设C(x)=A(x)B(x)

        我们把A(x),B(x)奇偶拆项,即A(x)=A_0(x)+xA_1(x)B(x)=B_0(x)+xB_1(x)

        然后C(x)=A_0(x)B_0(x)+x\big(A_0(x)B_1(x)+A_1(x)B_0(x)\big)+x^2A_1(x)B_1(x)
        我们分别计算x^0,x^1,x^2的系数。我们可以预处理出A_0,A_1,B_0,B_1DFT之后的结果,预处理的时候可以合并,于是这里总共只进行两次DFT
        然后还要进行三次IDFT,这里我们可以将其中两个IDFT合成一个,于是这里也只进行两次IDFT

        好了!现在让我们把这种方法用于实战当中!

        拆系数FFT
        对于一个模意义下的FFT(假设模数为m),我们假设m_0=\left\lfloor\sqrt m\right\rfloor
        使用带余数的除法,我们可以如此表示一个整数:k\cdot m_0+b

        那么对于原来的A(x),B(x),我们也用带余除法表示其每一项,于是现在就变成了这样:
        A(x)=m_0\cdot P_a(x)+Q_a(x),B(x)=m_0\cdot P_b(x)+Q_b(x)
        P_a(x)的系数是A(x)的各项系数除以m_0Q_a(x)的各项系数是A(x)的各项系数除以m_0的余数。P_b(x),Q_b(x)同理

        然后就变成了这样:C(x)=Q_a(x)Q_b(x)+m_0\big(P_a(x)Q_b(x)+Q_a(x)P_b(x)\big)+m_0^2P_a(x)P_b(x)
        计算就和上面的类似了

        这样拆系数是有好处的!当数字的大小降到了3*10^4时,卷积之后数字最大在10^{14}级别左右(一般达不到),这个级别的精度是可以保证的 me才不信,但是要在最后+0.5来四舍五入。数字大的时候一定要用long double,因为double精度只有1e15多一些,而long double接近1e19,感觉上更稳

        终于写完了……
        下面是一些自己的积累

        对于那种要求加起来等于某一个数才能累计的东西(比如dp),我们可以直接上FFT求解
        然而对于那种乘起来才能等于某一个数的东西,如果有说在模意义下,那么我们完全可以把乘法换成以原根为底的指数加法,感觉很厉害,例题SDOI2015序列统计

        ZJC同学的知乎专栏-一小时学会FFT
        miskcoo从多项式乘法到快速傅里叶变换
        多项式乘法运算终极版


        多项式求逆·多项式除法取模·多项式开根

        前置必备技能:FFT

        多项式求逆

        我们先搞一些定义
        称一个多项式的度deg(A)为多项式A(x)的最高次数
        然后定义带余除法:A(x)=D(x)B(x)+R(x) D(x)A(x)除以B(x)的商,R(x)是余数,且R(x)的度数小于B(x)
        (这给人的感觉就像是,从A(x)中不断的提取B(x),类似形如这样的数学题:\frac{x^3+4x^2+7x+12}{x+3}=x^2+x+4
        然后就可以写成这样A(x)\equiv R(x)\pmod {B(x)}

        然后多项式求逆,就是要求一个多项式B(x),满足
        A(x)B(x)\equiv 1\pmod{x^n}我们称B(x)是模x^n意义下,A(x)的逆元
        其实对x^n取模,相当于只保留这个多项式的{n-1}次项及以下的部分

        然后我们开始求解
        如果n=1的话,那么B(x)直接就是一个常数,它就是A(x)的常数项的逆元

        如果n>1,假设已经求出了A(x)\bmod~x^{\left\lceil \frac{n}{2} \right\rceil}意义下的逆元B'(x),然后大力推导一波:
        我们已知的是:
        \begin{align*} A(x)B(x) \equiv 1 \pmod { x^n } \end{align*} 那么显然的可以得到
        \begin{align*} A(x)B(x) \equiv 1 \pmod { x^{\left\lceil \frac{n}{2} \right\rceil} } \end{align*} 那么又因为我们已经有
        \begin{align*} A(x)B'(x) \equiv 1 \pmod { x^{\left\lceil \frac{n}{2} \right\rceil} } \end{align*} 所以两式相减可以得到(因为肯定不是A(x) \equiv 0
        \begin{align*} B(x) - B'(x) \equiv 0 \pmod { x^{\left\lceil \frac{n}{2} \right\rceil} } \end{align*} 然后我们把两边同时平方一下
        \begin{align*} B^2(x) - 2B(x)B'(x) + {B'}^2(x) \equiv 0 \pmod { x^n } \end{align*} 注意这里模数变成了x^n,因为平方之后的多项式,它的第n-1次项及以下部分都是由x^kx^{n-1-k}得来,而kn-1-k至少有一个它是小于\frac{n}{2}的,所以n-1次项以下部分全都是0。这也是为什么模数一开始要向上取整的原因,如果不向上取整,这一步的模数只能是x^{n-1}
        然后继续化式子,两边同时乘上一个A(x)
        \begin{align*} B(x) - 2B'(x) + A(x){B'}^2(x) \equiv 0 \pmod {x^n} \end{align*} 也就是说
        \begin{align*} B(x) = 2B'(x) - A(x){B'}^2(x) \pmod {x^n} \end{align*} 这样我们就可以递归的去求解,然后就大功告成了!
        (同时可以注意到,只要常数项有逆元,那么多项式就一定存在逆元)
        注意这里在实现的时候,需要把x^n项及以上的部分截掉,或者手动清空。不然多项式的长度将不可估量……
        时间复杂度:T(n)=T(\frac{n}{2})+O(n\log n)=O(n\log n)

        多项式开根

        其实多项式开根和多项式求逆是类似的
        我们现在要求一个B(x),满足B^2(x)\equiv A(x) \pmod {x^n}

        如果n=1,那么B(x)直接就是一个常数,它就是对A(x)的常数项开根号
        如果n>1,假设我们已经求到了{B'}^2(x) \equiv A(x) \pmod { x^{\left\lceil \frac{n}{2} \right\rceil} },然后进行一系列推导:

        首先我们有
        \begin{align*} B^2(x)\equiv A(x) \pmod { x^n } \end{align*}所以可以得到这个
        \begin{align*} B^2(x)\equiv A(x) \pmod { x^{\left\lceil \frac{n}{2} \right\rceil} } \end{align*}然后用已知和这个式子相减
        \begin{align*} B^2(x) - {B'}^2(x) \equiv 0 \pmod { x^{\left\lceil \frac{n}{2} \right\rceil} } \end{align*} 然后两边同时平方
        \begin{align*} { \left( B(x) + {B'}(x) \right) }^2 { \left( B(x) - {B'}(x) \right) }^2 \equiv 0 \pmod { x^n } \end{align*} 所以我们发现它是有两个解的!不过无所谓,我们取右边那个继续往下推导
        \begin{align*} { \left( B(x) - {B'}(x) \right) }^2 \equiv 0 \pmod { x^n } \end{align*} 然后是和上面差不多的步骤
        \begin{align*} B^2(x) - 2B(x)B'(x) + {B'}^2(x) \equiv 0 \pmod { x^n } \end{align*} 然后用A(x)代换B^2(x)
        \begin{align*} A(x) - 2B(x)B'(x) + {B'}^2(x) \equiv 0 \pmod { x^n } \end{align*} 移项,就有了
        \begin{align*} B(x) \equiv \frac{ A(x) + {B'}^2(x) }{ 2B'(x) } \pmod { x^n } \end{align*} 于是,开方被转化成了求逆元问题,不过感觉很麻烦的样子…
        时间复杂度:T(n)=T(\frac{n}{2})+T'(\frac{n}{2}) +O(n\log n)=O(n\log n),那个T'(n)是多项式求逆的复杂度
        感觉常数要上天了……

        miskcoo多项式除法及取模
        miskcoo多项式多点求值与快速插值
        miskcoo多项式求逆元
        Ender多项式相关
        LowestJN[Notes][多项式]杂记 · 多项式算法—多项式求逆 多项式取模 多项式开根


        柯西不等式

        \left(\sum {a_i}^2\right)\left(\sum {b_i}^2\right)\geq \sum\left(a_ib_i\right)^2
        感觉证明方式很神啊
        首先所有 a_i 都是 0 的情况很显然

        不然,构造二次函数:
        f(x)=\sum(a_i+xb_i)^2拆开得到:
        f(x)=\sum {a_i}^2+2x\sum a_ib_i+x^2\sum {b_i}^2这个函数显然时刻大于 0,根据判别式,有:
        \begin{align*} 4\sum(a_ib_i)^2-4\sum{a_i}^2\sum{b_i}^2 \leq 0 \\ \\ \sum{a_i}^2\sum{b_i}^2 \geq \sum(a_ib_i)^2 \end{align*} 原式得证


        \sqrt{N}分块:

        求和\sqrt{N}分块例题:BZOJ2956

        欧拉函数:

        欧拉函数如果i mod p = 0, 那么phi(i * p)=p * phi(i)的证明
        欧拉函数积性巧妙证明(数字矩阵辅助)
        欧拉定理&&欧拉函数
        三个重要的同余式——威尔逊定理、费马小定理、欧拉定理 + 求幂大法的证明
        欧拉定理extend证明–降幂技巧

        逆元:

        逆元ACdreamer

        中国剩余定理:

        中国剩余定理与扩展 Lucas定理与扩展 学习笔记

        元根和阶

        LinnBlanc_离散对数、元根

        离散对数与BSGS:

        离散对数BSGS
        扩展BSGS
        离散对数应用例题:BZOJ1420(modlog)

        容斥:

        FTD:容斥的原理及广义应用

        莫比乌斯反演:

        Mobius证明F(n)=\sum_{d|n}f(d)\implies f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d})\\F(n)=\sum_{n|d}f(d)=>f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)

        杜教筛:

        浅谈一类积性函数的前缀和
        莫比乌斯反演与杜教筛

        线性基:

        线性基定义&&板子
        线性基应用&&例题

        母函数:

        生成函数
        母函数与排列组合
        指数型母函数
        yuanxiaodi’s趣谈生成函数

        gauss消元:

        gauss_jordan矩阵求逆

        斯特林数:

        深入探究这个东西的资料貌似不是很多呢…感觉只要背住公式,能画柿子就好
        其实都可以去看百度百科了hhhhhh
        ACdreamer - 第一类Stirling数和第二类Stirling
        Ender有关斯特林数

        贝尔数:

        百度百科

        Pollard rho:

        Pollard rho算法详解
        Doggu:Miller-Rabin大质数判定以及Pollard-Rho大数提取因数

        Miller-Rabin:

        Matrix67:数论部分第一节:素数与素性测试
        Doggu:Miller-Rabin大质数判定以及Pollard-Rho大数提取因数


        其他

        ivorysi的数论学习笔记
        Bfk二项式反演证明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值