1.3 acwing.1296. 聪明的燕姿(难)
《信息学奥赛一本通》 , JLOI2014
1 | 城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。 |
思路:
抓住题目核心,也就是求一个数的所有正约数之和等于给定号码牌,这样的数有多少个。
比如S = 42,这个时候就有3个数满足条件:
41 = (1 + 41) == 42,20 = (1 + 2 + 4 + 5 + 10 + 20) == 42,26 = (1 + 2 + 13 + 26) == 42
约数与因数的区别:约数必须在整除的前提下才存在,而因数是从乘积的角度来提出的。
约数只能对在整数范围内而言,而因数就不限于整数的范围。
约数个数定理
定理: 若 $n=\prod_{i=1}^{m} p_{i}^{c_{i}}$ 则 $d_{i}=\prod_{i=1}^{m} c_{i}+1$.
证明:我们知道 $p_{i}^{c_{i}}$ 的约数有 $p_{i}^{0}, p_{i}^{1}, \ldots, p_{i}^{c_{i}}$ 共 $c_{i}+1$ 个,根据乘法原理, $n$ 的约数个数就是 $\prod_{i=1}^{m} c_{i}+1$
假设d为N的约数,d必然由N的质因数相乘得到。
参考题解:https://www.acwing.com/solution/content/10545/
观察约数之和的公式,猜测满足所有正约数之和等于给定号码牌的数非常少,所以用dfs暴搜。
应该先从小到大枚举p,
1 | for(p : 2,3,5,7,...) |
直接枚举p的话,素数个数非常多,时间复杂度很大,所以必须优化。
考虑特殊情况:
如果ai = 1的话,S = (1+Pi)的时候,因为Pi为质数,那么S-1也一定为质数,那么这个时候只需要判断S-1是否为质数即可。
如果不满足1,S只会有两种情况,就是一种情况包括一个因子里面有(1+Pi),另一种情况不包括(1+Pi),
S = (1+Pi)(1+Pj+Pj^2…..)
S = (1+Pi+Pi^2+…)(1+…..)这两种情况都可以看出来Pi ^2 <= S,所以我们dfs枚举Pi的上限就是$\sqrt S$。
找个实际的例子模拟一下,就会很清楚整个过程了。
代码:
1 |
|
1.4 acwing.1299. 五指山
《信息学奥赛一本通》
1 | 大圣在佛祖的手掌中。 |
思路:
参考文章:扩展欧几里得——裴蜀(贝祖)定理
参考资料:《算法笔记》,https://oi-wiki.org/math/gcd/
首先介绍裴蜀定理。(其实已经介绍过一遍了)
其内容是:
设a, b是不全为零的整数, 则存在整数x, y,使 $a x+b y=\operatorname{gcd}(a, b).$
对于任意的一组整数x、y,ax+by一定是gcd(a,b)的整数倍。
注意:裴蜀等式的解的个数不唯一!
举例:a=24,b=16,d = gcd(24,16) = 8,(x,y) = (-1,1) = (2,-1) = … ,这里就列出了两组解,它们可以称为裴
蜀数。
然后是扩展欧几里得算法。已经介绍过了欧几里得算法求最大公约数gcd。
而扩展欧几里得算法不仅能求最大公约数,还能求解裴蜀等式的一组整数解x、y。
下面叙述一下具体的数学形式的求解思路。
首先假设:我们已经通过扩展欧几里得算法求解出裴蜀等式的一组整数解$x_0,y_0$。
也即:$ax_0+by_0=gcd(a,b)=d$。
令:$a^{‘}=\frac a d,b^{‘}=\frac b d$。则有结论,裴蜀等式的通解有这样的形式:$\begin{cases}x=x_0+kb^{‘}\\ y=y_0-ka^{‘}\end{cases}$,其中k为任意整数。
验证上述解的形式是否裴蜀等式:$ax+by=a(x_0+kb^{‘})+b(y_0-ka^{‘})=d$,所以必然是等式的解。
下证等式的通解必然是满足上述形式:不妨设$x^{‘},y^{‘}$是等式的通解,则有:$ax^{‘}+by^{‘}=d$。
与等式$ax_0+by_0=d$联立可以求得:$a(x^{‘}-x_0)=b(y_0-y^{‘})$,则有:$a^{‘}(x^{‘}-x_0)=b^{‘}(y_0-y^{‘})$,所以
有:$b^{‘}|a^{‘}(x^{‘}-x_0)$,又:$(a^{‘},b^{‘})=1$,所以:$b^{‘}|(x^{‘}-x_0)$,即:$x^{‘}-x_0=kb^{‘}$,再代入
$a^{‘}(x^{‘}-x_0)=b^{‘}(y_0-y^{‘})$,有:$ka^{‘}=y_0-y^{‘}$。综上所述,上述解的形式必然是裴蜀等式的通解。
接下来讲解一下算法形式的求解思路。
设$a x_{1}+b y_{1}=\operatorname{gcd}(a, b)$,$b x_{2}+(a \bmod b) y_{2}=\operatorname{gcd}(b, a \bmod b)$。
由欧几里得定理可知: $\operatorname{gcd}(a, b)=\operatorname{gcd}(b, a \bmod b)$,所以 $a x_{1}+b y_{1}=b x_{2}+(a \bmod b) y_{2}$。
又因为 $a \bmod b=a-\left(\left\lfloor\frac{a}{b}\right\rfloor \times b\right)$,所以 $a x_{1}+b y_{1}=b x_{2}+\left(a-\left(\left\lfloor\frac{a}{b}\right\rfloor \times b\right)\right) y_{2}$,
$a x_{1}+b y_{1}=a y_{2}+b x_{2}-\left\lfloor\frac{a}{b}\right\rfloor \times b y_{2}=a y_{2}+b\left(x_{2}-\left\lfloor\frac{a}{b}\right\rfloor y_{2}\right)$。
因为 $a=a, b=b$, 所以 $x_{1}=y_{2}, y_{1}=x_{2}-\left\lfloor\frac{a}{b}\right\rfloor y_{2}$。
将 $x_{2}, y_{2}$ 不断代入递归求解直至递归边界 $x=1, y=0$ 回溯反解出$x_{1},y_{1}$。
扩展欧几里得算法代码:
1 |
|
由上面的代码可以求出裴蜀等式的一组特解,再通过通解公式我们就能得到全部解。
思路回到题目。
再介绍一下同余式的概念。形如$ax\equiv c(mod\;n)$的式子称为同余式,表示:(ax-c)mod n = 0
。
我们要求的就是满足方程-a*n+b*d=y-x
的b的最小正整数值,这些量都是整数。
- 当$(n,d)\nmid y-x$时,由于左边是常量n与d的线性组合,必然被(n,d)整除,所以方程肯定没有整数解。
- 当$(n,d)\mid y-x$时,对于裴蜀等式
n*x+d*y=(n,d)
,只要左右两边同乘$\frac {y-x} {(n,d)}$,就能转化为所求方程。
由裴蜀等式的通解知道:$b=b_0+k*\frac n {(n,d)}$,b的最小正整数值=$b_0\;mod\;\frac n {(n,d)}$。
原理:不论b0是个多大或者多小的一个数字,它通过k∗n/gcd(n,d)都能把这个数缩小到0−n/gcd(n,d)之间。
int get_mod(int a,int b) return (a % b + b) % b;// 将负余数转成正的
代码:
1 |
|