数论——约数之和、快速乘
数论——约数之和、快速乘
除了最基本的数学规律,一涉及到数论一点不会,所以说学点简单的数论知识吧,至少不至于一遇到就放弃。
AcWing 99 约数之和
来源:97. 约数之和 - AcWing题库
假设现在有两个自然数A和B,S是AB的所有约数之和。请你求出Smod9901的值是多少。假设现在有两个自然数 A 和 B, S 是 A^{B} 的所有约数之和。请你求出 S \bmod 9901 的值是多少。假设现在有两个自然数A和B,S是AB的所有约数之和。请你求出Smod9901的值是多少。
数据范围:0≤A,B≤5×107数据范围:0≤A,B≤5×10^7数据范围:0≤A,B≤5×107
分析与推导
质因数分解:将 A 分解为质因数的幂次形式,即 (A=p1a1⋅p2a2⋅⋯⋅pnan)(A = p_1^{a_1} \cdot p_2^{a_2} \cdot \dots \cdot p_n^{a_n})(A=p1a1⋅p2a2⋅⋯⋅pnan)
幂次变换:AB=p1a1⋅B⋅p2a2⋅B⋯⋯pnan⋅BA^{B}=p_{1}^{a_{1} \cdot B} \cdot p_{2}^{a_{2} \cdot B} \cdots \cdots p_{n}^{a_{n} \cdot B}AB=p1a1⋅B⋅p2a2⋅B⋯⋯pnan⋅B
因数和公式:若一个数的质因数分解为 (pk)(p^k)(pk),则其因数和为等比数列和 (1+p+p2+⋯+pk)(1 + p + p^2 + \dots + p^k)(1+p+p2+⋯+pk)。因此,(AB)(A^B)(AB) 的因数和为各质因数对应等比和的乘积: (p10+p11+p12+⋅⋅⋅+p1k1)∗(p20+p21+p22+⋅⋅⋅+p2k2)∗⋅⋅⋅∗(pn0+pn1+pn2+⋅⋅⋅+pnkn)\left (p_{1}^{0}+ p_{1}^{1}+p_{1}^{2}+···+p_{1}^{k1}\right )*\left ( p_{2}^{0}+p_{2}^{1}+p_{2}^{2}+···+p_{2}^{k2}\right )*···*\left ( p_{n}^{0}+p_{n}^{1}+p_{n}^{2}+···+p_{n}^{k_{n} }\right )(p10+p11+p12+⋅⋅⋅+p1k1)∗(p20+p21+p22+⋅⋅⋅+p2k2)∗⋅⋅⋅∗(pn0+pn1+pn2+⋅⋅⋅+pnkn)
对于每一个质因数ppp的计算:p0+p1+p2+⋅⋅⋅+pkp^{0}+p^{1}+p^{2}+···+p^{k}p0+p1+p2+⋅⋅⋅+pk
当kkk为偶数时:
式子可分解为:1+p1+p2+⋅⋅⋅+pk/2+pk/2+1+⋅⋅⋅+pk1+p^{1}+p^{2}+···+p^{k/2}+p^{k/2+1}+···+p^{k}1+p1+p2+⋅⋅⋅+pk/2+pk/2+1+⋅⋅⋅+pk
=1+p1+p2+⋅⋅⋅+pk/2+pk/2(p1+p2+⋅⋅⋅+pk/2)=1+p^{1}+p^{2}+···+p^{k/2}+p^{k/2}(p^{1}+p^{2}+···+p^{k/2})=1+p1+p2+⋅⋅⋅+pk/2+pk/2(p1+p2+⋅⋅⋅+pk/2)
=1+(1+pk/2)(p1+p2+⋅⋅⋅+pk/2)=1+(1+p^{k/2})(p^{1}+p^{2}+···+p^{k/2})=1+(1+pk/2)(p1+p2+⋅⋅⋅+pk/2)
=⋅⋅⋅⋅⋅⋅=······=⋅⋅⋅⋅⋅⋅
当kkk为奇数时,设k=2m+1k=2m+1k=2m+1:
式子可分解为:1+p1+p2+⋅⋅⋅+pm+pm+1+⋅⋅⋅+p2m+p2m+11+p^{1}+p^{2}+···+p^{m}+p^{m+1}+···+p^{2m}+p^{2m+1}1+p1+p2+⋅⋅⋅+pm+pm+1+⋅⋅⋅+p2m+p2m+1
=1+p2m+1+p1+p2+⋅⋅⋅+pm+pm+1+⋅⋅⋅+p2m=1+p^{2m+1}+p^{1}+p^{2}+···+p^{m}+p^{m+1}+···+p^{2m}=1+p2m+1+p1+p2+⋅⋅⋅+pm+pm+1+⋅⋅⋅+p2m
=1+p2m+1+(1+pm)(p1+p2+⋅⋅⋅+pm)=1+p^{2m+1}+(1+p^{m})(p^{1}+p^{2}+···+p^{m})=1+p2m+1+(1+pm)(p1+p2+⋅⋅⋅+pm)
=⋅⋅⋅⋅⋅⋅=······=⋅⋅⋅⋅⋅⋅
这样一来我们就利用分治的思想通过递归将原来的一长串式子给分解出来了。
代码解释
1、筛出质因数
- 利用试除法筛出质因数p1⋅p2⋅⋯⋅pnp_1\cdot p_2\cdot \dots \cdot p_np1⋅p2⋅⋯⋅pn
- 筛因数的同时将他们的次方a1⋅a2⋅⋯⋅ana_1\cdot a_2\cdot \dots \cdot a_na1⋅a2⋅⋯⋅an也记录下来,方便后面传参
void solve()
{cin >> n >> m;//n^m次方的约数和int res=1;for(int i=2; i*i<=n; i++){int cnt=0;while(n%i==0)//筛出所有p(只会是质数){cnt++; n/=i;}if(cnt) res=res%mod*sum(i,cnt*m)%mod;}//当n本身就是质数的时候由于i*i<=n所以i筛不到n//其实也可以直接让i<=n,但是这样是O(n)的复杂度非常高if(n>1) res=res%mod*sum(n,m)%mod;if(!n) res=0;cout << res;
}
2、通过sumsumsum函数递归求当前因数次方和
解释一下为什么偶数有两个公式:
原始公式:p10+p11+p12+⋅⋅⋅+p1kp_{1}^{0}+ p_{1}^{1}+p_{1}^{2}+···+p_{1}^{k}p10+p11+p12+⋅⋅⋅+p1k
变换之后:1+p1(p0+p1+p2+⋅⋅⋅+pk−1)1+p^1(p^{0}+p^{1}+p^{2}+···+p^{k-1})1+p1(p0+p1+p2+⋅⋅⋅+pk−1)
这样的话就不用再写一长串推导式了,直接变成奇数下一次递归求解
int sum(int p, int k)//p^0+···+p^k
{if(k==0) return 1;if(k%2==0)//偶数return 1+p%mod*sum(p,k-1)%mod;//图省事可以将偶数提一个出来变成奇数在下一次递归求解// return (sum(p,k/2)+qp(p,k/2+1)*sum(p,k/2-1)%mod)%mod;//原始公式return sum(p, k/2)* (1 + qp(p, k/2+1)) % mod;//奇数
}
AcWing 90 64位整数乘法
来源:90. 64位整数乘法 - AcWing题库
输出一个整数,表示a*b mod p
的值。
数据范围:1≤a,b,p≤1018数据范围:1≤a,b,p≤10^{18}数据范围:1≤a,b,p≤1018
思路
当一个数的幂次很大的时候我们不能一次次乘,所以引入了快速幂。但是当像这个乘数很大一乘就会爆long long 的时候该怎么办呢?
这时候就有人说了:高精度。但是别忘了,这里还要取mod,这样就必须进行数学计算。于是就引出了快速乘
原理其实已经见过好多次了:二进制分解
由于任何数都可以用若干2的次方数相加得到,所以可以将数字拆成若干个2的次方依次相乘,乘的过程中不断进行取模
代码
int qpow(int a, int b, int c)
{int ans=0;while(b){if(b&1) ans=(ans+a)%c;a=(a*2)%c;//相当于b*2,由于是乘法,谁乘都一样b>>=1;}return ans%c;
}
void solve()//a^b%p
{int a,b,p;cin >> a >> b >> p;cout << qpow(a,b,p);
}