【小结】数论
置顶
欧几里得算法
问题:求 \(\gcd (a,b)\)。
设 \(a>b\) 那么显然 \(\gcd (a,b)= \gcd (b,a-b)\)。
不断做这个操作,等价于 \(\gcd (a,b)= \gcd (b,a\%b)\)。
然后不断递归下去。一般来说我们吧保证 \(a,b\geq 0\)。
当 \(b=0\) 时,\(\gcd (a,b)=a\)。这是递归的尽头。
分析一下时间复杂度,设 \(a>b\)。
若 \(b\leq \frac{a}{2}\),那么下一轮的 \(a\) 至少折半;
若 \(b>\frac{a}{2}\),则 \(a\%b<\frac{a}{2}\),那么下一轮的 \(b\) 就小于 \(\frac{a}{2}\)。再用一次递归就可以把 \(a\) 折半。
时间复杂度:\(\mathcal O( \log V)\)。
扩展欧几里得算法
问题:求 \(ax+by= \gcd (a,b)\) 的一组解。
首先,对 \(ax+by= \gcd (a,b)\) 进行一次辗转相除。
则有 \(bx_1+(a\%b)y_1= \gcd (b,a\%b)\)。
容易发现 \(\gcd (a,b)= \gcd (b,a\%b)\)。
于是联立两式,得到 \(ax+by=bx_1+(a\%b)y_1\)。
注意到 \(a\%b=a-\lfloor \frac{a}{b} \rfloor \times b\)。
带入式子,得到 \(ax+by=bx_1+(a-\lfloor \frac{a}{b} \rfloor \times b)y_1\)。
进一步展开,得到 \(ax+by=bx_1+ay_1-\lfloor \frac{a}{b}\rfloor \times b \times y_1=ay_1+b(x_1-\lfloor \frac{a}{b} \rfloor \times y_1)\)。
所以 \(x=y_1\),\(y=x_1-\lfloor \frac{a}{b} \rfloor \times y_1\) 是一组合法的值。
那么递归的尽头是什么呢?
和欧几里得算法一样,当 \(b=0\) 的时候,\(\gcd (a,b)=a\),方程变成了 \(ax+0y=a\)。容易发现 \(x=1,y=0\) 是方程的一组解(\(y\) 可以取任意值,但习惯性取 \(0\))
那么不断递归往上传值,我们就可以得到这个方程的一组解啦!
时间复杂度:\(\mathcal O( \log V)\)。
记这组解为 \(x_0,y_0\)。
这里还有我的一个小疑问,就是这里解出的特解 \(x_0,y_0\) 不会爆 long long 吗?我研究了一下,正常情况是不会的,证明如下:
利用数学归纳法,假设 \(|x_1|\leq \frac{a \ mod \ b}{d},|y_1|\leq \frac{b}{d}\)。(显然你 \(x=1,y=0\) 经过一轮递归传值之后,变成 \(x=0,y=1\),然后就肯定满足这个条件了)
然后 \(|x|=|y_1| \leq \frac{b}{d}\)。
然后 \(|y|=|x_1-\lfloor \frac{a}{b} \rfloor \times y_1|\leq \frac{a \ mod \ b}{d}+\frac{b}{d}\times \lfloor \frac{a}{b} \rfloor=\frac{a \ mod \ b+b\times \lfloor \frac{a}{b} \rfloor}{d}=\frac{a}{d}\)。
所以一步一步推下去,最后特解 \(x_0,y_0\) 肯定不超过 \(\frac{b}{d}\) 和 \(\frac{a}{d}\)。
应用:解不定方程
问题:求 \(ax+by=c\) 的一组解,或报告无解。
裴蜀定理:方程有解当且仅当 \(\gcd (a,b)|c\)。
有了这个结论,我们就可以判无解。
然后对于有解的情况,把 \(x_0,y_0\) 同时乘 \(c/ \gcd (a,b)\) 一定是方程的一组解。
这组解还是记为 \(x_0,y_0\)。
通解:\(x=x_0+k\times (b/ \gcd (a,b))\),\(y=y_0-k\times (a/ \gcd (a,b))\)。
设 \(tb=b/ \gcd (a,b)\),\(ta=a/ \gcd (a,b)\)。
那么 \(x\) 的最小非负整数解就是 \((x_0\%tb+tb)\%tb\)。
\(y\) 同理。
应用:解同余方程
问题:求 \(ax\equiv c(mod\ b)\) 的最小非负 \(x\)。
问题可以转化为 \(ax+by=c\),然后直接解就行。
易错点
-
要确保 \(a\) 和 \(b\) 的值非负,不然 \(\gcd\) 就是负的,有必要时 \(a,b,c\) 取反。
-
不要忘了裴蜀定理判有解,\(c\% \gcd (a,b)=0\)。
-
跑完扩欧之后,要由 \(ax+by= \gcd (a,b)\) 的解得到原方程的解。需要 \(x*=(c/ \gcd (a,b))\)。
-
如果要求最小非负整数解,那么就是 \((x_0\%tb+tb)\%tb\)。
-
求最小正整数解的时候,若最小非负整数解是 \(0\),那么需要特判变成 \(tb\)。
一些题目
P1082 [NOIP 2012 提高组] 同余方程
纯板子。转换成 \(ax+by=1\) 然后直接求 \(x_0\),最后输出 \((x_0\%tb+tb)\%tb\) 即可。无解都不用判。
P2613 【模板】有理数取余
读入的话可以边读边取模。
模数是 \(19260817\),记为 \(c\)。
转化成 \(bx+cy=a\)。然后求一组解。
判一下 \(a\% \gcd (b,c)\) 是否等于 \(0\)。
最后输出取模后的结果即可。也就是最小非负整数解。
P1516 青蛙的约会
首先是转化题目。在一个环形相遇相当于同余。
那么根据题意,得到:
\(x+mt\equiv y+nt(mod\ L)\)。
转化,得到:
\(x+mt+Lp=y+nt\)。
移项,得到:
\((m-n)t+Lp=y-x\)。
其中 \(t\) 和 \(p\) 为未知量。
这不就是个不定方程?
令 \(a=m-n,b=L,c=y-x\) 跑扩欧。
但是注意 \(a\) 有可能小于 \(0\)。但是 \(b\) 一定是正的。
那么把 \(a\) 和 \(c\) 取反。\(b\) 不能取反!!!我就是一直错在这里,因为 \(\gcd (a,b)\) 必须保证 \(a\) 和 \(b\) 是正的。
但是这样求出的 \(y\) 是真正的 \(y\) 的相反数。但在这题我们并不关心 \(y\),我们关心的只是 \(x\) 的最小非负整数解。所以这样求出的 \(x\) 还是正确的。
然后注意判无解。
然后还是求出原方程的解。
最后输出最小非负整数解。
P5656 【模板】二元一次不定方程 (exgcd)
这个题是 exgcd 的精髓,细节非常多。
首先无解是好判的。
然后求出 \(x\) 最小正整数解,求出对应的 \(y\)。如果在这种情况下 \(y\) 都小于等于 \(0\) 了,那么无正整数解。
然后相应的求出 \(y\) 的最小正整数解,求出对应的 \(x\)。
如果无正整数解,直接输出 \(x\) 和 \(y\) 的最小正整数解;
如果有正整数解,那么输出这四个值。然后正整数解的个数就是 \(( \max x- \min x)/tb\)。
CF710D Two Arithmetic Progressions
困难的一道题。但是感觉没到 \(*2500\)。
就是说,先列出方程 \(a_1k+b_1=a_2l+b_2\)。
然后推式子,\(a_1k-a_2l=b_2-b_1\)。
跑扩欧,求出 \(k_0,l_0\)。
但是因为这题是等差数列,所以项数肯定不能是负的。
我们需要求出求出这玩意的最小非负整数解。(即两个都为非负整数)
由于 \(b\) 是 \(-a_2\) 是负的,所以 \(k\) 增加的同时 \(l\) 也增加。所以先把 \(x\) 变成最小非负整数,然后看 \(y\),如果 \(y<0\),那么把 \(y\) 变成最小非负整数,\(x\) 随之变化。相当于考虑非负的限制在 \(x\) 还是 \(y\)。
这个题难点在于它有一个范围需要推。而且这个范围的上下取整比较恶心。
\(L\leq a_1(k_0+tb\times p)+b_1\leq R\)。
求 \(p\) 的取值范围。
解得 \(\frac{L-b_1-a_1k_0}{a_1tb}\leq p \leq \frac{R-b_1-a_1k_1}{a_1tb}\)。
然后分别上取整,下取整即可。
注意 C++ 默认的下取整是“向 \(0\) 取整”,而 floor 才是真正的向下取整。
最后设左端为 \(l\),右端为 \(r\),那么输出 \(r-l+1\) 即可。
P2421 [NOI2002] 荒岛野人
直接枚举 \(m\)。
然后对于每个 \(m\),检验的时候枚举两个人,判断这两个人会不会相遇。如果有相遇的,那么这个 \(m\) 不合法。
设枚举的是 \(i\) 和 \(j\)。
那么 \(C_i+P_ix\equiv C_j+P_jx(mod \ m)\)。
然后转化为不定方程 \((P_i-P_j)x+my=C_j-C_i\)。
跑扩欧。求 \(x\) 的最小非负整数解。
如果这个 \(x\leq L_i\) 且 \(x\leq L_j\),那么相遇。
无解需要直接跳过。这个要判一下。
P3986 斐波那契数列
自己随便挑的题。感觉还不错的题目。
首先考虑这个特殊的斐波那契数列是啥玩意。
\(a,b,a+b,a+2b,2a+3b,3a+5b,5a+8b,\dots\)
容易发现规律。对于不是 \(1,2\) 项的项,\(a\) 的系数是斐波那契的某一项,\(b\) 的系数是斐波那契的后一项。而这两个系数必然是正整数。
设最后等于 \(k\) 的这个位置的 \(a\) 的系数是 \(x\)。显然 \(b\) 的系数非负。所以 \(b\) 的系数要小于等于 \(k\),不然肯定无正整数解。
所以枚举过程是 \(\mathcal O( \log V)\) 的。
然后目前枚举 \(a\) 的系数是 \(t\),\(b\) 的系数是 \(p\),那么 \(tx+py=k\)。你要求有多少 \((x,y)\)。
还是可以扩欧。
题目限定 \(x,y\) 的范围只说了都是正整数,所以求正整数解的个数即可。
正整数解的个数还是 \((R-L)/tb+1\)。(如果有的话)
没有或者无解的话直接判一下跳过。
乘法逆元
定义:对于整数 \(a\) 和模数 \(m\)(\(m>1\)),如果存在整数满足:
\(ax\equiv 1(mod \ m)\)
则称 \(x\) 是 \(a\) 在模 \(m\) 意义下的乘法逆元。记作 \(a^{-1}\)(或 \(inv(a)\))。
定理 \(1\):\(a\) 在模 \(m\) 意义下有乘法逆元的充要条件为:
\(\gcd (a,m)=1\)
求单个逆元的方法
扩欧
首先逆元的定义式就是一个同余方程。
把同余方程转化成不定方程,就是 \(ax+my=1\)。
然后用扩欧解出最小非负 \(x\)。
这种是最通用的求单个数逆元的方法。只要 \(a\) 和 \(m\) 互质,即逆元存在,那么就可以求解。
时间复杂度:\(\mathcal O( \log V)\)。
费马小定理
费马小定理:若 \(p\) 为质数,则 \(a^{p-1}\equiv 1(mod \ p)\)。(证明的话,它是欧拉定理的一个特殊情况,后面讲到欧拉定理的时候会详细证明)
若 \(a^{p-1}\equiv 1(mod \ p)\),那么 \(a\times a^{p-2}\equiv 1(mod \ p)\)
根据定义,\(a\) 的一个逆元为 \(a^{p-2}\)。
所以用快速幂求出 \(a^{p-2}\) 即可。
这种方法仅限于 \(p\) 为质数的时候使用。
时间复杂度:\(\mathcal O( \log V)\)。
求多个逆元的方法
递推法
递推式:\(inv_i=(p-\lfloor \frac{p}{i} \rfloor) \times inv[p\%i]\%p\)。
证明:
令 \(p=ki+r\),其中 \(k=\lfloor \frac{p}{i} \rfloor\),\(r=p\%i\)。
在模 \(p\) 意义下:
\(ki+r \equiv 0(mod \ p)\)。
两边同乘 \(i^{-1} \times r^{-1}\):
\(kr^{-1}+i^{-1}\equiv 0(mod \ p)\)。
因此:
\(i^{-1}\equiv -kr^{-1}(mod \ p)\)。
即:
\(inv_i\equiv(p-k)\times inv_r(mod \ p)\)。
这种只能求 \(1\sim n\) 的逆元。
时间复杂度:\(\mathcal O(n)\)。
阶乘法
先求 \(fac_i\) 表示前缀积。
然后可以用求单个逆元的方法求出 \(invfac_n\),其中 \(invfac\) 表示前缀积的逆元。
然后倒推出 \(invfac_i\)。递推式为 \(invfac_i=invfac_{i+1}\times(i+1)\)。
最后 \(inv_i\) 就是 \(invfac_i\times fac_{i-1}\)。
这种可以求任意数列 \(a_1,a_2,\dots,a_n\) 的逆元。
时间复杂度:\(\mathcal O(n)\)。
一些题目
P1082 [NOIP 2012 提高组] 同余方程
逆元板子题,但是只能用 exgcd,因为模数不一定是质数。
\(ax\equiv 1(mod \ p)\) 转化为 \(ax+py=1\) 直接扩欧求出最小非负 \(x\) 就是答案。
P3811 【模板】模意义下的乘法逆元
线性求逆元板子题。
用上面的两种方法都行,直接去做就行。
P5431 【模板】模意义下的乘法逆元 2
这种都太板了吧,显然我们要求一串数的逆元,只能用第二种方法因为 \(a_i\leq 10^9\)。
直接用第二种方法就行。但是注意 \(invfac\) 的处理是 \(invfac_i=invfac_{i+1}\times a_{i+1}\)。
P1593 因子和
首先要求所有的因数之和,套路的把 \(a\) 质因数分解。
然后如果 \(a\) 中质因子 \(p\) 有 \(c\) 个,那么 \(a^b\) 中质因子有 \(bc\) 个。
我们把这些质因子组合起来,分配进去相当于:
\((1+p_1+p_1^{2}+\dots+p_1^{bc_1})\times(1+p_2+p_2^{2}+\dots+p_2^{bc_2})\times\dots\times(1+p_n+p_n^{2}+\dots+p_n^{bc_n})\)
容易想到等比数列求和,公式为 \(\frac{p^{bc+1}-1}{p-1}\)。然后分解质因数,求 \(p-1\) 的逆元乘上去就行。
诶?\(p-1\) 一定存在逆元吗?
不!当 \(p-1\equiv 0(mod \ 9901)\) 时,除数为 \(0\),无意义!
那咋办。\(p-1\equiv 0(mod \ 9901)\) 的时候,\(p\equiv 1(mod \ 9901)\)。也就是说这个求和的每一项都是 \(1\)。一共 \(bc+1\) 项。直接加上 \(bc+1\) 即可。
P2265 路边的水沟
简单题。题目就是要在 \(n+m\) 步里选 \(m\) 步往左走。
直接输出 \(C_{n+m}^{m}\) 即可。
处理 \(fac_i\) 和 \(invfac_i\) 就可以 \(\mathcal O(1)\) 计算 \(C_{n+m}^{m}\)。
P2054 [AHOI2005] 洗牌
有点诈骗的题目。
首先题目看起来及其复杂。而且那个分牌的机制就很吓人。
但是仔细一看,可以把牌分成两打。前面那一打显然是 \(x\to 2x\),后面那一打,是 \(x\to \lceil\frac{x}{2}\rceil\) 吗?不这并不好做。这及其难做。
那再次寻找后面一半的规律。
\(4\to 1\),\(5\to 3\),\(6\to 5\)。
寻找规律,特别艰难的发现 \(x\to 2x\%(n+1)\)。
前面那一打也不会超过 \(n+1\)。也就是 \(2x=2x \% (n+1)\)。
所以都可以统一为 \(2x\%(n+1)\)。
转化为同余方程:\(x2^m\equiv L(mod \ (n+1))\)。
转化为不定方程:\(2^mx+(n+1)y=L\)。
求 \(x\) 的最小非负解即可。
P4881 hby 与 tkw 的基情
好难啊。
设 \(n\) 为奇数,如果不为奇数则减 \(1\)。
令 \(m=\frac{n+1}{2}\)。
求 \(S=1\times 26+3\times 26^2+\dots+n\times 26^m\)。
那么 \(26S=1\times 26^2+3\times 26^3+\dots+n\times 26^{m+1}\)。
那么两式相减,\(25S=n\times26^{m+1}-(1352\times \sum_{i=0}^{m-2} 26^i+26)\)。
等比数列直接代,\(S=\frac{n\times26^{m+1}-(1352\times \frac{26^{m-1}-1}{25}+26)}{25}\)。
求 \(25\) 的逆元并带入即可。
扩展中国剩余定理
由于中国剩余定理和扩展中国剩余定理解决的是同样的问题,且用的时间和用空间大致相同,而扩展中国剩余定理适用面更广。
得出结论:中国剩余定理屁用没有。
嗯。那我们跳过 CRT 直接来学 exCRT。
问题:
给定一组同余方程:
\(x\equiv a_1(mod \ m_1)\)
\(x\equiv a_2(mod \ m_2)\)
\(\dots\)
\(x\equiv a_n(mod \ m_n)\)
求最小非负整数解 \(x\)。
此类问题在数学上称之为解同余方程组问题。
原理:
设有 \(n\) 个同余方程:
\(x\equiv a_1(mod \ m_1)\)
\(\dots\)
\(x\equiv a_n(mod \ m_n)\)
借用数学归纳法的思想,假设 \(x\) 是前 \(k-1\) 个方程的一个特解,则通解 \(x+ \operatorname{lcm}(m_1,m_2,\dots,m_{k-1})\times t\)。其中 \(t\) 为任意整数。
第 \(k\) 个方程要有解,则:
\(x+ \operatorname{lcm}\times t\equiv a_k(mod \ m_k)\)
要有解。
利用扩欧可以解出 \(t\),如果扩欧无解那整个同余方程组就无解。
这个 \(t\) 使得 \(x'=x+ \operatorname{lcm}\times t\) 是前 \(k\) 个方程的一个特解。
同理,可以求出前 \(k+1,k+2,\dots,n\) 个方程的解。
时间复杂度:\(\mathcal O(n \log n)\)。
一些题目
P4777 【模板】扩展中国剩余定理(EXCRT)
板子。就是按照刚刚的步骤去做。
扩欧中 \(A= \operatorname{lcm},B=a_i,C=b_i-ans\)。其中 \(ans\) 为上一轮中求出的最小非负解。
然后在 \(x*=(C/d)\) 的过程中,有可能就爆掉了。
所以我们需要使用一种高科技就是“龟速乘”。
我是第一次碰到这个东西。
它可以 \(\mathcal O( \log V)\) 的实现乘法操作。
就是把 \(a\times b\) 转化为 \(b\) 个 \(a\) 相加,再用快速幂的思想,把 \(b\) 二进制分解,就可以边加边取模,这样就不会爆 ll 了。
然后需要说明的是,因为每次求出的都是 \(k-1\) 轮的最小非负整数解,所以你要再减它肯定是不行的。那么你只能让它加上正的东西。说白了就是加上 \(x\times \operatorname{lcm}\)。其中 \(x\) 为前面解方程的最小非负整数解。
注意,一开始赋初始值的时候,赋的是第一个方程。
\(\operatorname{lcm}=a_1,ans=b_1\%a_1\)。
注意一定是 \(b_1\%a_1\) 而不是 \(b_1\)。然后 \(i\) 从 \(2\) 遍历到 \(n\)。
或者初始值 \(\operatorname{lcm}=1,ans=0\) 就行。这样更好。然后 \(i\) 从 \(1\) 遍历到 \(n\)。以后都使用这种。
因为我们需要保证最小非负。
在这个题中不会错,但是其他题多多少少有卡这个的点。
P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪
这个嘛。。。你直接把 exCRT 的代码交过去就能过。
UVA756 Biorhythms
想不到吧。我们在 exCRT 中做到红题了。
恭喜你被红题卡住了
其实这题可以暴力。就很明显。
但是为了练习 exCRT,可以再打一遍。求出特解之后小了就调整,大了也调整。
然后就和板子差不多。
P3868 [TJOI2009] 猜数字
\(b_i|(n-a_i)\)。
\(n-a_i=kb_i\)。
\(a_i+kb_i=n\)。
\(n\equiv a_i(mod \ b_i)\)。
把所有的组合起来,就是同余方程组。直接 exCRT。
好嘛就把 \(a_i\) 和 \(b_i\) 换了个位置。
CF338D GCD Table
\(*2900\)。但是感觉真没有屠龙勇士困难。
首先这个题,相当于就是要确定一个 \((x,y)\),然后使得 \((x,y)\) 往后延伸 \(k\) 个都满足条件。
考虑一个性质:
若有解,那么一定在 \(x= \operatorname{lcm}(a_1,a_2,\dots,a_k)\) 的时候有解。
显然 \(x\) 一定要是 \(\operatorname{lcm}\) 的倍数。
那么设它为 \(k\times \operatorname{lcm}\)。
如果 \(x=k\times \operatorname{lcm}\) 的时候满足条件,那么 \(\gcd (k\times \operatorname{lcm},y)=a_1\),\(\gcd (k\times \operatorname{lcm},y+1)=a_2,\dots, \gcd (k\times \operatorname{lcm},y+k-1)=a_k\)。
这样的话首先 \(y\) 一定得是 \(a_i\) 的倍数。
然后 \(\operatorname{lcm}\) 肯定也是 \(a_i\) 的倍数。
所以 \(\gcd\) 已经有 \(a_i\) 了。
剩下的就是要保证没有其他多余的因数了。也就是 \(\gcd (k,y)=1\)。
那为什么不让 \(k\) 是 \(1\) 呢?不然不就多个限制。
那么确定了 \(x= \operatorname{lcm}\),就来列方程组。
\(y\) 必须满足:
\(y\equiv 0(mod \ a_1)\)
\(y+1 \equiv 0(mod \ a_2)\)
\(\dots\)
\(y+k-1 \equiv 0(mod \ a_k)\)
全部移项,可以得到:
\(y \equiv 0(mod \ a_1)\)
\(y \equiv -1(mod \ a_2)\)
\(\dots\)
\(y \equiv -1+k(mod \ a_k)\)
又一个 exCRT。
因为 \(y\) 是正整数,所以如果 \(y\) 是 \(0\) 的话,直接把 \(y\) 弄成 \(\operatorname{lcm}\)。
但是弄完之后注意判断:
-
\(x\)(即 \(\operatorname{lcm}\))得在范围内。
-
\(y\) 也得在范围内。
-
对于 \(x,y\) 这组解还得再判断一下,因为不一定成立,可能还有多余的因数。这组解只是更有可能成立。有解代表 \(x,y\) 成立,但是解出了 \(x,y\) 并不代表有解。
P4774 [NOI2018] 屠龙勇士
目前做过最难的题。调死我了,浪费一下午。
首先因为这个东西是按顺序打怪,所以打每个怪用的剑是固定的。直接 multiset 插入、删除、查询最后一个小于等于 \(x\) 的值。如果没有的话,那么直接取第一个。取完之后如果打怪成功那就放一把新的剑进去。
设剑的攻击力为 \(atk\)。
那么剑确定了。现在就是数学问题。
\(a_i-atk(ans+ \operatorname{lcm}\times t)\equiv 0(mod \ p_i)\)。
\(a_i-atk\times ans\equiv \operatorname{lcm}\times atk \times t(mod \ p_i)\)。
那么也就是 \(\operatorname{lcm}\times atk \times t+p_iy=a_i-atk\times ans\)。
联立形成同余方程组(已经转化为了不定方程组),然后用 exCRT 搞出结果。
此时解出了 \(t\),然后 \(ans+=t\times \operatorname{lcm}\)。
这里的 \(\operatorname{lcm}\) 指的是 \(p_i\) 出去与 \(atk\) 公因数之后的最小公倍数而不是 \(p_i\) 本身的最小公倍数。相当于就是 \(tb\) 的最小公倍数。而 \(tb\) 和 \(\operatorname{lcm}\) 互质。
然后注意最后如果砍都砍不死一个怪的话,那就相当于这个怪在自己一直扣血,每次扣 \(p_i\)。这种情况是不存在的。设把每个怪都干死的最小 \(x\) 是 \(ma\),那么最后必须一直加 \(\operatorname{lcm}\) 直到 \(ans\geq ma\)。
输出 \(ans\)。
注意中间还有各种 __int128 还有龟速乘的细节。注意注意。
启示:exCRT 中 \(\operatorname{lcm}\) 的本质并不是模数的最小公倍数,而是 \(tb\)(即 \(x\) 的最小正周期)的最小公倍数。因为只要变换是 \(tb\) 的倍数,方程就仍然成立。前面的理解可能有点小差错。
欧拉函数
定义:欧拉函数 \(\varphi(n)\) 表示小于等于 \(n\) 正整数中与 \(n\) 互质的数的个数。
性质:
-
对于质数 \(p\),\(\varphi(p)=p-1\)。
-
当 \(p\) 是质数时,\(\varphi(p^k)=p^{k-1}(p-1)\)。
-
若 \(m,n\) 互质(\(\gcd (m,n)=1\)),则 \(\varphi(mn)=\varphi(m)\varphi(n)\)。这也证明了 \(\varphi\) 是积性函数。
-
若 \(a|x\),则 \(\varphi(ax)=a\varphi(x)\)。
求单个欧拉函数的值
问题:求 \(\varphi(n)\) 的值。
把 \(n\) 质因数分解,那么 \(n=p_1^{k_1}p_2^{k_2}p_3^{k_3}\dots p_c^{k_c}\)。
根据性质 \(2\),那么 \(\varphi(p_i^{k_i})=p_i^{k_i-1}(p_i-1)\)。根据性质 \(3\),那么 \(\varphi(n)=p_1^{k_1-1}p_2^{k_2-1}\dots p_c^{k_c-1}(p_1-1)(p_2-1)\dots (p_c-1)=\frac{n(p_1-1)(p_2-1)\dots(p_c-1)}{p_1p_2\dots p_c}\)。
也可以写成 \(\varphi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})\dots (1-\frac{1}{p_c})\)。
我们只需要对其进行质因数分解,一开始 \(ans=n\),后面对于 \(n\) 的每个质因数 \(x\) 令 \(ans=ans/x\times(x-1)\)。最后返回 \(ans\) 即可。
时间复杂度:\(\mathcal O(\sqrt{n})\)。
求多个欧拉函数的值
问题:求 \(i=1 \sim n\) 的 \(\varphi(i)\)。
使用欧拉筛筛除欧拉函数。
for (i=2;i<=n;i++)
{
if (!phi[i]) phi[i]=i-1,p[++k]=i;
for (j=1;j<=k&&1ll*i*p[j]<=n;j++)
{
if (i%p[j]==0)
{
phi[i*p[j]]=p[j]*phi[i];//性质 4,
break;
}
else phi[i*p[j]]=phi[i]*phi[p[j]];//性质 3
}
}
时间复杂度:\(\mathcal O(n)\)。
欧拉反演
一种技巧。
首先有一个结论:\(x=\sum_{d|x} \varphi(d)\)。
证明:
令 \(x=p_1^{\alpha_1}p_2^{\alpha_2}\dots p_k^{\alpha_k}\)。
那么 \(\sum_{d|x} \varphi(d)=\sum_{\beta_i=0}^{\alpha_i}\prod_{j=1}^{k} \varphi(p_j^{\beta_i})=\prod_{i=1}^{k} \sum_{\beta_i=0}^{\alpha_i} \varphi(p_i^{\beta_i})=\prod_{i=1}^{k}(1+p_i-1+\dots+p_i^{\alpha_i}-p_i^{\alpha_i-1})=\prod_{i=1}^{k} p_i^{\alpha_i}=x\)。
用这个性质可以反演做一些题。
有需要的时候用这个结论转化到因数。
一些题目
UVA10179 Irreducable Basic Fractions
求 \(\varphi(x)\)。直接用求单个 \(\varphi(x)\) 的方法即可。
UVA11327 Enumerating Rational Numbers
线性处理出 \(\varphi(x)\),然后处理出 \(\varphi\) 的前缀和 \(sum_x\)。
如果 \(n=1\),那要特判,直接输出 \(0/1\)。
否则,\(n--\),继续做下面的操作。
二分出分母。然后枚举分子,最后枚举到第 \(k\) 个,就可以确定分子。
P1891 疯狂 LCM
经典推式子。
\(\sum_{i=1}^{n} \operatorname{lcm}(n,i)\)
\(=\sum_{i=1}^{n} \frac{ni}{gcd(n,i)}\)
\(=n\sum_{i=1}^{n} \frac{i}{gcd(n,i)}\)
\(=n\sum_{d|n}\sum_{i=1}^{n}[ \gcd (i,n)=d]\times \frac{i}{d}\)
\(=n\sum_{d|n}\sum_{i=1}^{n}[ \gcd (\frac{i}{d},\frac{n}{d})=1]\times \frac{i}{d}\)
\(=n\sum_{d|n}\sum_{i=1}^{\frac{n}{d}}[ \gcd (i,\frac{n}{d})=1]\times i\)
因为 \(\gcd (n,x)= \gcd (n,n-x)\)。
所以当 \(n>3\) 时,与 \(n\) 互质的数成对出现。(加和为 \(n\))
当 \(n=2\) 时,仅有一个 \(1\) 满足条件。而 \(\varphi(2)=1\),所以 \(f(2)=\frac{n}{2}\times \varphi(2)\)。
然后对于 \(n>3\),成对出现,有 \(\frac{\varphi(n)}{2}\) 对,那么 \(f(n)=\frac{n}{2}\times \varphi(n)\)。
那么 \(f(1)=1\),当 \(x>1\) 时,\(f(x)=\frac{x}{2}\times \varphi(x)\)。
这样我们线性筛出 \(\varphi(x)\),求出 \(f(x)\),就可以处理这个式子了。
最后枚举 \(n\) 的因数 \(d\),求因数的 \(f(d)\) 的总和,乘 \(n\) 就是答案。
CF1295D Same GCDs
设 \(\gcd (a,m)= \gcd (a+x,m)=d\)。
那么 \(\gcd (\frac{a}{d},\frac{m}{d})= \gcd (\frac{a+x}{d},\frac{m}{d})=1\)。
因为 \(\gcd (a+x,m)= \gcd ((a+x) \mod \ m,m)\),\(a+x\) 相当于 \([0,m-1]\) 这个区间向右平移 \(a\) 格。因为 \(\gcd (x,m)= \gcd (x+m,m)\),那么每次平移,模 \(m\) 的余数不变。所以就相当于没有平移。计算 \(\varphi(\frac{m}{d})\) 即可。
P2158 [SDOI2008] 仪仗队
设左下角坐标为 \((0,0)\)。
抽象问题。
转化为 \(\gcd(x,y)=1\)。
那么答案就是 \(\sum_{x=0}^{n-1}\sum_{y=0}^{n-1} [\gcd(x,y)=1]\)。
输出 \(\sum_{x=1}^{n-1} 2\times\varphi(x)+1\)。
P3601 签到题
典题。
显然 \(qiandao(i)=i-\varphi(i)\)。
所以 \(\sum_{i=l}^{r}qiandao(i)=\sum_{i=l}^{r}(i-\varphi(i))=\frac{(l+r)(r-l+1)}{2}-\sum_{i=l}^{r}\varphi(i)\)。
\(l,r\) 已知。所以目标转化为求 \(\sum_{i=l}^{r} \varphi(i)\)。
题目给出的一个比较特殊的限制是 \(r-l\leq 10^6\)。没有这个条件显然是不可做的。所以考虑从这个条件入手。
首先可以处理出 \(10^6\) 以内的质数以及 \(\varphi\)。(这里写复杂了,其实质数的 \(\varphi\) 就是它减 \(1\))
然后考虑如何对 \(l\sim r\) 的这些数做质因数分解。
枚举倍数,再枚举因数是 \(\mathcal O(n\sqrt{n})\) 的。
枚举因数,再枚举倍数是 \(\mathcal O(n \log n)\) 的。
因为枚举倍数是枚举到的一定是倍数。而枚举因数会有很多枚举的浪费。
所以直接枚举 \(10^6\) 以内的质数 \(p\)。再枚举它在 \([l,r]\) 以内的倍数。对于这个倍数 \(x\),就存在这么一个质因数。令 \(\varphi_x=\varphi_x/p\times(p-1)\)。再记录一个 \(val_x\),把枚举到的质数除掉。
存储的话,可以在 \(x-l\) 的位置上存储 \(x\) 的值。这样只要开 \(10^6\) 的数组。
最后,如果 \(x\) 还没分解完,也就是 \(val_x>1\),那么 \(val_x\) 也是 \(x\) 的质因数。按前面一样再处理一下即可。
最后别忘了一开始还有个求和的式子。
CF870F Paths
容易发现,有 \(4\) 种情况。
设 \(f_i\) 为 \(i\) 的最小质因子。
-
当 \(\gcd(x,y)\neq 1\) 时,\(d(x,y)=1\)。
-
当 \(\gcd(x,y)=1\) 且 \(f_x\times f_y\leq n\),\(d(x,y)=2\)。
-
当 \(\gcd(x,y)=1\) 且 \(f_x\times f_y>n\) 且 \(\min(x,y)\leq \lfloor \frac{n}{2} \rfloor\),\(d(x,y)=3\)。
-
当 \(\gcd(x,y)=1\) 且 \(f_x\times f_y>n\) 且 \(\min(x,y)>\lfloor \frac{n}{2} \rfloor\),\(d(x,y)=0\)。
考虑统计这个东西。
-
对于不互质的数的对数,就是 \(\frac{(n-1)(n-2)}{2}-\sum_{i=2}^{n} \varphi(n)-1\)。
-
不太好处理,正难则反,可以用总方案数减去其他方案数。
-
这种情形下,\(f_x,f_y\) 一定至少有一个大于 \(\sqrt{n}\)。也就是一个大于 \(\sqrt{n}\) 的质数。预处理 \(S_i\) 表示 \(f_k=i\) 的 \(i\) 的个数。那么枚举较小的那个,然后就可以算出较大的那个的取值范围,对 \(S_i\) 做前缀和就可以快速计算。
-
与 \(3\) 同理,只是 \(\lfloor \frac{n}{2} \rfloor\) 从下界变为了上界。
欧拉定理与扩展欧拉定理
欧拉定理
如果正整数 \(a\) 和 \(n\) 互质,那么 \(a^{\varphi(n)}\equiv 1(mod \ n)\),其中 \(\varphi(n)\) 是欧拉函数。
当 \(n\) 为质数时,\(\varphi(n)=n-1\),此时欧拉定理退化为费马小定理,得到 \(a^{n-1}\equiv 1(mod \ n)\)。
此时,费马小定理可以在 \(p\) 为质数且 \(a\) 与 \(p\) 互质的时候求 \(a\) 在模 \(p\) 意义下的逆元。
应用:求乘法逆元
仅供启发,实际上毫无用处。
若 \(\gcd(a,n)=1\),那么 \(a^{\varphi(n)-1}\equiv a^{-1}\)。
时间复杂度:\(\mathcal O(\sqrt{n})\)。
应用:指数降幂
这个应用还比较重要。
推论:若 \(\gcd (a,n)=1\),则 \(a^b\equiv a^{b \ mod \ \varphi(n)}(mod \ n)\)。
证明非常好证,令 \(b=q\times \varphi(n)+r\),其中 \(0\leq r<\varphi(n)\),则 \(a^b\equiv a^{q\times \varphi(n)+r}\equiv {a^{\varphi(n)}}^q\times a^r\equiv 1^q\times a^r\equiv a^r\equiv a^{b \ mod \ \varphi(n)}(mod \ n)\)。
扩展欧拉定理
对于任意正整数 \(a,n\) 和任意非负整数 \(b\):
若 \(b<\varphi(n)\),则 \(a^b\equiv a^b(mod \ n)\)
若 \(b\geq \varphi(n)\),则 \(a^b\equiv a^{b \ mod \ \varphi(n)+\varphi(n)}(mod \ n)\)。
这个定理没有 \(a,n\) 互质的限制,是通用的。但是注意,使用时略微麻烦,得判断 \(b\) 与 \(\varphi(n)\) 的大小关系。
一些题目
P5091 【模板】扩展欧拉定理
板子。注意 \(b\) 很大,所以需要降幂。这也是欧拉定理存在的意义。欧拉定理就是帮助我们降幂的。当 \(b\) 很大时,快速幂都承受不了,欧拉定理可以帮我们取模。
那这个题,读入 \(b\) 的时候就可以一边读一边对 \(\varphi(m)\) 取模。然后判断过程中是否有过对 \(\varphi(m)\) 取模。如果有,那么最后的 \(b\) 还要加上 \(\varphi(m)\),否则保持不变。
此时的 \(b\) 一定是小于 \(2\varphi(m)\) 的。那 \(b\) 就在 \(2\times 10^8\) 以内。跑快速幂即可。
HDU4704
也就是把一个数分成若干份的方案数。
我一开始想到的是 \(\sum_{i=1}^n i^{n-i}\),不过似乎不太好做。
我们换一种思考方式。\(n\) 个物品,我们可以分成 \(1,2,\dots,n\) 组,也就是插 \(0,1,\dots,n-1\) 个板。
一共可插的板是 \(n-1\) 个,所以答案为 \(\sum_{i=0}^{n-1}C(n-1,i)=2^{n-1}\)。
因为 \(2\) 和 \(10^9+7\) 显然互质,所以可以直接使用欧拉定理。
CF17D Notepad
根据题意,第一位有 \(b-1\) 种选择,后面 \(n-1\) 位有 \(b\) 种选择。
所以答案为 \((b-1)\times b^{n-1} \ mod \ c\)。然后如果这个值为 \(0\) 的话就输出 \(c\)。
对于 \(n\) 在取模的时候判断一下是否有过大于 \(\varphi(c)\) 即可使用扩展欧拉定理取模并快速幂。
P4139 上帝与集合的正确用法
题目大意:输出 \(2^{2^{2^{2^\dots}}} mod \ p\) 的值。
因为到最后的时候,\(a_{n-1}=\infty\),所以 \(a_{n-1}\leq \varphi(p)\)。
\(a_n=2^{a_{n-1}} \ mod \ p=2^{a_{n-1} \ mod \varphi(p)+\varphi(p)} \ mod \ p\)。当 \(p=1\) 时,停止递归,直接返回 \(0\)。
模数就是 \(p\to \varphi(p) \to \varphi(\varphi(p))\to \dots\)
因为 \(\varphi(p)<p\),所以不会死循环。
当 \(p=1\) 时,递归截止。
当 \(p\) 为大于 \(1\) 的奇数时,\(\varphi(p)\) 为偶数。
当 \(p\) 为偶数时,\(\varphi(p)\leq \frac{p}{2}\)。
所以时间复杂度为 \(\mathcal O(T\log p)\)。
HDU2837
直接递归是 \(\log\) 的,难点在于取模。什么时候要加 \(\varphi(n)\),什么时候不要加。
有两种处理方法(第一种仅供参考,建议使用第二种):
-
我自己想到的方法。在函数返回值和快速幂返回值里加一个参数 flag 表示有没有被取模过,这样就可以知道下一层递归要不要加 \(\varphi(n)\)。
-
这种更加精妙。可以把所有取模操作换成 get_mod 函数。
int get_mod(int x,int mod)
{
if (x<mod) return x;
return x%mod+mod;
}
然后如果没有被取模过当然是没有问题。
那如果被取模过了,此时的 \(x\) 因为加 \(mod\) 肯定大于 \(mod\)。所以下次的时候还会大于 \(mod\),最后输出的结果当然是结果 \(\% mod + mod\) 咯。
这就自动达到了我们想达到的目的。
然后直接按这个递归,然后传模数进去即可。
CF906D Power Tower
感觉还好。但是有 \(*2700\)。以前是黑。哎,做的题咋都不能交。
也是一样的。\(f(l,r,mod)\) 表示 \([l,r]\% mod\) 的价值。
然后当 \(mod=1\) 或者 \(l=r\) 的时候结束循环。
前面说了,\(mod\) 到 \(1\) 的次数是 \(\log\) 的,所以复杂度是对的。
然后取模的话使用前面说的两种方法的一种就行。(建议第二种)
复杂度是 \(\mathcal O(m\times \min (\log p,r-l+1))\)。
P2350 [HAOI2012] 外星人
极度难懂的题。但代码及其好写。
注意到所有质因数都经历一个变成 \(2\) 再变成 \(1\) 的过程。
那么第一次操作,会把 \(2\) 变成 \(1\),其他质因子挑一个出来减 \(1\)。那么其他质因子都是奇数,所以第一轮会有偶数,反正可以提出来 \(2\) 的几次方。如果第一轮没有 \(2\),那就会浪费一轮,让质因子里存在 \(2\)。
第二次操作,一定存在 \(2\) 了,那么会消去一个 \(2\),并产生新的 \(2\)。
后面的操作,一直在消 \(2\),其他的一直在产生 \(2\)。
所以后面的操作次数总和是大家能产生的 \(2\) 的个数的总和。
令 \(f_i\) 表示 \(i\) 能产生的 \(2\) 的个数。
若 \(p\) 为质数,则 \(f_i=f_{i-1}\)。
否则,\(f_{a\times b}=f_a+f_b\)。
加性函数,可以线性筛上 DP。
啊那么做完了。
最后答案就是 \(\sum_{i=1}^{n} f_{p_i}\times {q_i}+[p_i 中不存在 2]\)。
代码非常短。是思想非常好的一道题。
BSGS 算法
用来解决离散对数问题。
问题:给定一个质数 \(p\),整数 \(a\) 和 \(b\)(其中 \(0<a<p,0\leq b<p\)),求最小的非负整数 \(x\),使得:
\(a^x\equiv b(mod \ p)\)
或判断这样的 \(x\) 不存在。
做法:当 \(i=1\sim m\),\(j=0\sim m\) 时,令 \(x=im-j\in[0,m^2]\) 且能取遍 \([0,m^2]\)。
令 \(m=\lceil\sqrt{p}\rceil\),有 \(m^2\geq p\)。足够覆盖 \([0,p]\)。
将 \(x=im-j\) 代入原方程:
\(a^{im-j}\equiv b(mod \ p)\)
\(a^{im}\times ({a^{j}})^{-1}\equiv b(mod \ p)\)
\(a\) 要有逆元,所以 \(a\) 要与 \(p\) 互质。
两边同时乘 \(a^j\):
\(a^{im}\equiv b\times a^j(mod \ p)\)
此时未知数只有 \(i\) 和 \(j\)。
接着就是 meet-in-the-middle 的思想。
BS(Baby Step): 用来枚举 \(j\)。对于每个 \(b\times a^j\),放入哈希表。如果要求是正整数,那 \(j\) 就从 \(0\) 枚举到 \(m-1\)。否则,\(j\) 就从 \(0\) 枚举到 \(m\)。
GS(Giant Step): 用来枚举 \(i\)。对于 \(a^{im}\) 查看是否存在于哈希表中,如果存在,那说明找到了一个 \(a^{im}\equiv b\times a^j(mod \ p)\)。\(x=im-j\) 就是合法的一个解。而这个解一定是最小的。因为 \(i\) 是从小到大枚举的,\(i\) 更大的时候 \(x\) 肯定更大。
使用 unordered_map 存入哈希表的过程我们假定是 \(\mathcal O(1)\) 的。
那么时间复杂度就是 \(\mathcal O(\sqrt{p})\) 的。
注意:在 \(a\) 和 \(p\) 互质的情况下我们才能用 BSGS 求解。若 \(p\) 是质数,那么若 \(a\) 与 \(p\) 不互质,那么:
若 \(b\) 与 \(p\) 互质,那么显然无解。
若 \(b\) 与 \(p\) 不互质,那么显然最小非负整数解为 \(1\)。
所以在 \(p\) 为质数的时候,BSGS 可以完成这个问题。
一些题目
P3846 【模板】BSGS / [TJOI2007] 可爱的质数
模板题。按照上面说的去做就行。
甚至不用判无解。
P4861 按钮
也挺板子的。
题目说的显然是 \(K^x\equiv 1(mod \ M)\) 的最小正整数解。
那只需要把 \(j\) 的取值范围改成 \(0\sim m-1\),然后注意判无解。
P4454 [CQOI2018] 破解 D - H 协议
题目看起来很难的样子。
但是我们只需要根据 \(A\equiv g^a(mod \ P)\) 求出 \(a\),然后求出 \(B^a\) 即可。
P2485 [SDOI2011] 计算器
三合一。
第一问不用多说。直接快速幂。
第二问,直接 exgcd。
第三问,直接 BSGS,然后注意判无解的时候,若 \(a\%p=0\) 且 \(b\%p=0\),那也是有解的,返回 \(1\)。其他情况下若 \(a\%p=0\) 就是无解。
P3306 [SDOI2013] 随机数生成器
BSGS 最困难的一集。感觉并不比屠龙勇士简单。
首先 \(x_{i+1}=a\times x_i+b\)。
那么 \(x_i=a\times x_{i-1}+b\)。
所以 \(x_i=a(a(a(\dots a(ax_1+b)\dots )+b)+b)+b\)。
显然有 \(i-1\) 个 \(a\) 相乘。
然后最外层有个 \(b\)。最内层的 \(b\) 的系数是 \(a^{i-2}\)。
所以 \(x_i=x_1\times a^{i-1}+b\times \sum_{j=0}^{i-2} a^j\)。
那么 \(x_1\times a^{i-1}+b\times \sum_{j=0}^{i-2} a^j \equiv t(mod \ p)\)。
所以 \(x_1\times a^{i-1}+b \times \frac{a^{i-1}-1}{a-1}\equiv t(mod \ p)\)。
所以 \(x_1\times a^{i-1}+\frac{b}{a-1}\times a^{i-1}-\frac{b}{a-1}\equiv t(mod \ p)\)。
所以 \((x_1+\frac{b}{a-1})\times a^{i-1}\equiv t+\frac{b}{a-1}(mod \ p)\)。
所以 \(a^{i-1}\equiv \frac{t+\frac{b}{a-1}}{x_1+\frac{b}{a-1}}(mod \ p)\)。
直接用 BSGS 求解即可。
需要注意的点:
-
特判 \(a=0\)。只要 \(b=t\) 就有解。否则无解。
-
特判 \(a=1\)。因为此时没有逆元。
-
特判 \(x_1=t\) 的情况。这样可以判掉 \(t+\frac{b}{a-1}=x_1+\frac{b}{a-1}=0\) 的情况。
P4884 多少个 1?
套用上一题的代码,令 \(x_1=1,a=10,b=1\),然后去做。
注意开 __int128,有些东西需要转 ll 处理。
exBSGS 算法
BSGS 算法有一个缺陷,就是只有 \(\gcd (a,p)=1\) 时,才能使用 BSGS。
若不保证,那么就是 exBSGS,原理如下:
\(a^{x-1}\times a\equiv b(mod \ p)\)
\(a\times a^{x-1}+py=b\)
裴蜀定理判断是否有解。
设 \(d=exgcd (a,p)\),在有解时,等式两边都有 \(d\),除掉。
\(\frac{a}{d} \times a^{x-1}+\frac{p}{d}y=\frac{b}{d}\)
再转化回同余方程,\(\frac{a}{d}\times a^{x-1}\equiv \frac{b}{d}(mod \ \frac{p}{d})\)。
因为 \(d\) 是 \(a\) 和 \(p\) 的最大公约数,所以 \(\gcd(\frac{a}{d},\frac{p}{d})=1\)。即 \(\frac{a}{d}\) 的逆元存在。
那么 \(a^{x-1}\equiv(\frac{a}{d})^{-1}\times \frac{b}{d}(mod \ \frac{p}{d})\)。
若 \(\gcd(a,\frac{p}{d})=1\),则可以使用 BSGS 求解。
否则,继续迭代。
注意该做法找到的不一定是最小解。
假设迭代次数为 \(tot\),则最后的结果为 \(x+tot\),可以在 \([0,tot]\) 内枚举寻找这个最小解。
迭代次数最多是 \(\log\) 的。
所以时间复杂度:\(\mathcal O(\log^2 p+\sqrt{p})\)。
一些题目
P4195 【模板】扩展 BSGS / exBSGS
板子。直接按照上面写的去做就行。
注意特判 \(b=1\) 和 \(p=1\) 的情况。
注意返回值要是很小的值。

浙公网安备 33010602011771号