AcWing 97.约数之和
题目:
假设现在有两个自然数 A 和 B,S 是 A^B 的所有约数之和。
请你求出 S mod 9901 的值是多少。
输入格式
在一行中输入用空格隔开的两个整数 A 和 B。
输出格式
输出一个整数,代表 S mod 9901 的值。
数据范围
0≤ A,B ≤ 5×10^7
输入样例:
2 3
输出样例:
15
注意: AA 和 BB 不会同时为 00。
思路:
A = p 1 k 1 ∗ p 2 k 2 ∗ p 3 k 3 ∗ . . . ∗ p n k n A = p1^{k1}*p2^{k2} * p3^{k3}*...*pn^{kn} A=p1k1∗p2k2∗p3k3∗...∗pnkn
因数的个数: ( k 1 + 1 ) ∗ ( k 2 + 1 ) ∗ ( k 3 + 1 ) ∗ . . . ∗ ( k n + 1 ) (k1+1)*(k2+1)*(k3+1)*...*(kn+1) (k1+1)∗(k2+1)∗(k3+1)∗...∗(kn+1)
因数和: ( p 1 0 + p 1 1 + . . . + p 1 k 1 ) ∗ ( p 2 0 + p 2 1 + . . . + p 2 k 2 ) ∗ . . . ∗ ( p n 0 + p n 1 + . . . + p n k n ) (p1^0+p1^1+...+p1^{k1})*(p2^0+p2^1+...+p2^{k2})*...*(pn^0+pn^1+...+pn^{kn}) (p10+p11+...+p1k1)∗(p20+p21+...+p2k2)∗...∗(pn0+pn1+...+pnkn)
设置函数 s u m ( p , k ) = ( p 0 + p 1 + . . . + p k ) sum(p,k)=(p^0+p^1+...+p^k) sum(p,k)=(p0+p1+...+pk)
若 k k k 为奇数:
s u m ( p , k ) = ( p 0 + p 1 + . . . + p k / 2 + p k / 2 + 1 + . . . + p k ) sum(p,k)=(p^0+p^1+...+p^{k/2}+p^{k/2+1}+...+p^k) sum(p,k)=(p0+p1+...+pk/2+pk/2+1+...+pk)
= ( 1 + p k / 2 + 1 ) ∗ ( p 0 + p 1 + . . . + p k / 2 ) =(1 + p^{k/2 + 1})*(p^0 + p^1 + ... + p^k/2) =(1+pk/2+1)∗(p0+p1+...+pk/2)
= ( 1 + p k / 2 + 1 ) ∗ s u m ( p , k / 2 ) =(1 + p^{k/2 + 1})*sum(p, k/2) =(1+pk/2+1)∗sum(p,k/2)
若 k k k 为偶数:
s u m ( p , k ) = 1 + p ∗ ( p 0 + p 1 + . . . + p k − 1 ) sum(p,k)=1 + p * (p^0 + p^1 + ... + p^{k-1}) sum(p,k)=1+p∗(p0+p1+...+pk−1)
= 1 + p ∗ s u m ( p , k − 1 ) =1 + p * sum(p, k - 1) =1+p∗sum(p,k−1)
代码:
package 基本算法.递推与递归.约数之和;
import java.util.Scanner;
public class Main {
public static final int MOD = 9901;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int A = in.nextInt();
int B = in.nextInt();
int res = 1;
for(int i = 2; i <= A; i++) {
int s = 0;
while(A % i == 0) {
s++;
A /= i;
}
if(s != 0) {
res = res * sum(i, s*B) % MOD;
}
}
if(A == 0) res = 0;
System.out.println(res);
in.close();
}
public static int sum(int p, int k) {
if(k == 0) return 1;
if(k % 2 == 0) return (p % MOD * sum(p, k-1) + 1) % MOD;
return (1 + qmi(p, k/2+1)) % MOD * sum(p, k/2)% MOD;
}
public static int qmi(int p, int k) {
p %= MOD;
int res = 1;
while(k != 0) {
if((k & 1) != 0) res = res * p % MOD;
p = p*p % MOD;
k >>= 1;
}
return res;
}
}