[复习]数论相关内容
[复习]数论相关内容
因为是男神讲的课,所以直接按照他的课件推过来吧。
\(CRT\)&\(ExCRT\)
\(CRT\)
求解方程组:
其中满足\(m_1,m_2,...,m_n\)之间两两互质。
令\(M=\prod m_i\),显然最终的答案可以在模\(M\)意义下求解。
考虑单个求解,合并答案。假设对于第\(i\)个方程,能够找到一个\(x_i\),使得\(x_i\equiv 1(mod\ m_i)\),同时模\(\displaystyle \frac{M}{m_i}\)为\(0\),那么显然就可以在模\(M\)意义下对于答案贡献一个\(x_ia_i\)了。
因为\(x_i\)是\(\displaystyle \frac{M}{m_i}\)的倍数,定义\(\displaystyle M_i=\frac{M}{m_i}\)。
所以有\(x_i=kM_i\equiv 1(mod\ m_i)\),所以\(x_i\)就是\(M_i\)在模\(m_i\)意义下的逆。
这样子答案就算完了,\(\displaystyle \sum(x_ia_i)\)。
其实不如直接\(ExCRT\)好理解。
\(ExCRT\)
不保证所有的\(m_i\)互质。那么显然最终的答案就是在模\(lcm(m_1,m_2,...,m_n)\)意义下进行的。
考虑如何合并两个方程的答案。
假设就是合并:
首先肯定要合并模数为\(lcm(m_1,m_2)\)。
显然有:\(\displaystyle x=k_1m_1+a_1=k_2m_2+a_2\)。
化简后就是\(\displaystyle k_1m_1-k_2m_2=a_2-a_1\)
\(m_1,m_2,a_1,a_2\)都是常数,这玩意就是一个\(exgcd\)求解了。
如果\(exgcd\)无解显然整个方程组都无解,否则求解后得到\(x\),合并模数之后就得到了一个新的方程,然后接着把所有方程都合并就好了。
卡特兰数
似乎有着好几种不同的递推式,事实上只是因为前面到底有几个\(1\)而产生的不同,本质上没有区别。
这里就理解为\(n\)个物品出入栈的方案数吧。
大概前几项就是:\(1,2,5,14,42,132,...\)
通项公式:\(\displaystyle C_n=\frac{1}{n+1}{2n\choose n}=\frac{(2n)!}{n!(n+1)!}={2n\choose n}-{2n\choose n-1}\)
递推公式:\(\displaystyle C_n=C_{n-1}\frac{4n-2}{n+1}\)
一般常见的问题答案是卡特兰数的有:括号配对、出入栈、多边形的三角形划分等。
第一类斯特林数、第二类斯特林数
戳这里
感觉写得比较详细了吧。
不重复写了。
组合数
这个太常见了,懒得怎么写了。。。
斐波那契数列
递推公式懒得写,都知道
通项公式:\(\displaystyle f(n)=\frac{\sqrt 5}{5}((\frac{1+\sqrt 5}{2})^n-(\frac{1-\sqrt 5}{2})^n)\)
一些奇怪的式子:
\(\displaystyle \sum_{i=1}^n f(i)=f(n+2)-1\)
\(\displaystyle \sum_{i=1}^n f(i)^2=f(n)*f(n+1)\)
\(\displaystyle \sum_{i=1}^n if(i)=n*f(n+2)-f(n+3)+2\)
\(\displaystyle \sum_{i=1}^n f(2i-1)=f(2n)-f(2)+f(1)\)
\(\displaystyle \sum_{i=1}^n f(2i)=f(2n+1)-f(1)\)
还有些奇怪的结论,原来写过一次了,戳这里
Bell数
\(n\)的集合划分数,显然是第二类斯特林数的前缀和。
从下标\(0\)开始:\(1,1,2,5,15,52,203,877,4140,21147,115975\)
递推式:\(\displaystyle B_{n+1}=\sum_{i=0}^n {n\choose i}B_{i}\),即枚举\(1\)所在的集合。
实际上就是我们平时所说的拆分数???
\(Lucas\)定理&\(ExLucas\)
\(Lucas\)定理
解决组合数取模问题。
在模质数意义下有:\(\displaystyle {n\choose m}={n/p\choose m/p}*{n\%p\choose m\%p} mod\ p\)
递归求解即可。
这个过程很像\(p\)进制分解的过程,所以利用这个东西可以出一些有意思的题目。
比如【UOJ#275】、【UOJ#300】。
拓展\(Lucas\)
适用于\(p\)为非质数的组合数取模问题。
考虑将\(p\)分解质因数得到\(\displaystyle p=\prod p_i^{k_i}\)
那么我们等价于对于每个质因子分开做,最后\(CRT\)合并答案。
现在的问题在于如何求解对于每个质数的\(k_i\)次幂的答案。
组合数\(\displaystyle {n\choose m}=\frac{n!}{m!(n-m)!}\)。
只有不互质才存在逆元,那么对于阶乘而言,我们先拿出所有的\(p\)这个因子,剩余部分求逆,最后再还原。
显然\(n!\)中\(p\)因子的个数是:\(\displaystyle \sum_{i=1} \frac{n}{p^i}\)。当然这里都是整除。
假装这个东西也可以写成一个函数叫做\(f(n)\)。
那么我们可以得到\(\displaystyle f(n)=f(\frac{n}{p})+\frac{n}{p}\),这样子就可以在\(O(log)\)的时间里求出含有\(p\)的因子的个数。
现在完成了第一步,去掉了\(n!\)中的\(p\)的因子,然而还有其他的数要求逆。
举个例子:
这里分成了三个部分,其中一个部分由\(p\)的若干次方组成,而最后那个部分可以递归处理。
那么我们要求解的就是前面那个丢到了\(p\)的倍数的部分。
前半部分按照\(p^k\)分组,在上面例子中是按照\(9\)分组,显然\(i\equiv i+p(mod\ p)\)。
所以分组后可以写成:\((1*2*4*5*7*8)*(10*11*13*14*16*17)*19\)。
显然前两组完整的在模\(9\)意义下是相等的,后最后多出来的部分个数不会超过\(9\)。
所以可以\(p^k\)暴力求出一组的结果,剩下的直接快速幂即可,而多出来的那个\(19\)直接暴力乘。
这样子的复杂度是\(O(p^k)\)级别的。
既然能够求阶乘取模的结果,那么就可以求组合数了,统计\(p\)因子的个数,如果上下正好抵消那么就可以求逆计算答案,否则模意义下的答案就是\(0\)。
这样子,对于每个质因子求解答案,最终\(CRT\)合并即可。
复杂度为\(O(\sum p_i^{k_i})\)。
\(Miller-Rabin\)素数测试
基于费马小的概率素数判定方法。
费马小定理:对于质数\(p\)而言,任意数\(x\)满足\(x^{p-1}\equiv 1(mod\ p)\),这也是质数求逆直接快速幂的依据。
然而费马小的逆命题并不成立,存在少量特殊的数虽然不是质数却满足费马小,可以百度找找。
也因为这个,所以\(Miller-Rabin\)是概率算法。
基于考虑如果\(x^k\equiv 1\),那么\(x^{k/2}\)只能是\(-1\)或者\(1\)。否则不合法。
因为费马小的逆否命题是成立的,所以先判断\(x^{p-1}\)在模意义下是否为\(1\),做一个初步的筛选。
\(x\)直接随机就好了,反复做多遍,将\(p-1\)拆分为\(2^t*k\)的形式,那么从\(x^k\)开始,每次将其平方进行判断(这样子保证最终一定会出现\(1\))。
如果所有过程合法的话我们就认为是一个质数。似乎专门构造数据是卡的掉的QwQ。
\(Pollard-Rho\)大整数分解
一个在大约是\(O(n^{\frac{1}{4}})\)的时间中分解大整数的算法。因为要用\(Miller-Rabin\)判断质数,所以也存在概率问题。(如果你知道所有质数就没有这个烦恼了)
每次找到一个约数,然后分成两个部分递归分解,如果当前部分用\(Miller-Rabin\)判断之后已经是一个质数了则直接返回。
考虑一个极端情况,如果当前数只由两个根号级别的质数相乘得到,那么随便\(rand\)到一个它的约数的概率是\(\displaystyle \frac{1}{\sqrt n}\),不在我们可以接受的范围之内。
一种更加优秀的做法是考虑两个数\(x,y\)做差,检查其差值是否为一个约数。如果\(gcd(abs(x-y),n)\)即不等于\(1\),也不等于\(n\),那么它就是一个约数,就可以拆分为两部分递归处理。
定义一个函数\(g(x)=(x*x+c)mod\ n\),\(c\)随意取。每次让\(x\)动,而\(y\)每隔一段时间动。但是这样子取的时候,\(x\)是会出现环的,因为先是一段不会重复的数,最终进入到了一个环,这个过程画出来像一个\(\rho\),所以这个算法名字后面带了一个\(Rho\)。如何判断环呢?令\(x\)每次走一步,\(y\)每两次走一步,这样子总是会相遇。
如果当前分解没有找到一个约数,那么调整\(c\)的值继续分解即可。
具体复杂度不会证明,找个板子记一下就好啦。
\(BSGS\) & \(ExBSGS\)
求解\(y^x\equiv z(mod\ p)\)。
\(BSGS\)
满足条件\(gcd(y,p)=1\)时使用\(BSGS\)。
这是一个分块做法。
令\(x=am-b,m=\sqrt p\)。
则有\(\displaystyle y^{x}=y^{am-b}\)
那么式子可以写成:\(\displaystyle y^{am}\equiv z*y^{b}(mod\ p)\)
那么右边只有\(\sqrt p\)种取值方法,开一个哈希表全部记下来。
枚举左边的\(a\)值,直接暴力查哈希表里面有没有对应的值,如果有直接还原答案即可。
因为\(x\)一定小于\(p\),所以\(a\)的取值也只有\(\sqrt p\)个,所以总的复杂度就是\(O(\sqrt p)\)级别的,额外加上哈希表之类的复杂度。
\(ExBSGS\)
不满足互质的条件时使用\(ExBSGS\)。
仍然考虑上面的方程\(y^x\equiv z(mod\ p)\)。
设\(d=gcd(y,p)\),显然如果\(z\)不能被\(d\)整除的话,那么无解。
否则的话,除掉一个\(d\),得到方程\(\displaystyle \frac{y}{d}y^{x-1}\equiv \frac{z}{d}(mod\ \frac{p}{d})\)。
即当前的\(p\)变成了\(\displaystyle \frac{p}{d}\),继续除掉\(gcd\),直到\(gcd\)为\(1\)。
那么此时左边前面带了一个系数,右边仍是一个已知整数,并且满足了互质的情况。
那么解出当前情况下的解,给答案加上一个除掉\(gcd\)的次数\(k\)就好了。
具体的戳这里
莫比乌斯反演
杜教筛
min_25筛
这三个东西戳这里