题目地址:
https://www.acwing.com/problem/content/99/
假设现在有两个自然数 a a a和 a a a, s s s是 a b a^b ab的所有约数之和。请你求出 s m o d 9901 s\mod9901 smod9901的值是多少。
输入格式:
在一行中输入用空格隔开的两个整数
a
a
a和
b
b
b。
输出格式:
输出一个整数,代表
s
m
o
d
9901
s\mod9901
smod9901的值。
数据范围:
0
≤
a
,
b
≤
5
×
1
0
7
,
a
+
b
>
0
0≤a,b≤5×10^7, a+b>0
0≤a,b≤5×107,a+b>0
约数之和有公式,参考https://blog.csdn.net/qq_46105170/article/details/113815655。对于一个正整数 x x x,若其质因子分解是 x = p 1 α 1 p 2 α 2 . . . p k α k x=p_1^{\alpha_1}p_2^{\alpha_2}...p_k^{\alpha_k} x=p1α1p2α2...pkαk,那么 x x x的约数个数是 ( 1 + p 1 + p 1 2 + . . . + p 1 α 1 ) ( 1 + p 2 + p 2 2 + . . . + p 2 α 2 ) . . . ( 1 + p k + p k 2 + . . . + p k α k ) (1+p_1+p_1^2+...+p_1^{\alpha_1})(1+p_2+p_2^2+...+p_2^{\alpha_2})...(1+p_k+p_k^2+...+p_k^{\alpha_k}) (1+p1+p12+...+p1α1)(1+p2+p22+...+p2α2)...(1+pk+pk2+...+pkαk)。那么若 a = p 1 α 1 . . . p k α k a=p_1^{\alpha_1}...p_k^{\alpha_k} a=p1α1...pkαk,那么 a b a^b ab的约数个数是 ( 1 + p 1 + . . . + p 1 b α 1 ) ( 1 + p 2 + . . . + p 2 b α 2 ) . . . ( 1 + p k + . . . + p k b α k ) (1+p_1+...+p_1^{b\alpha_1})(1+p_2+...+p_2^{b\alpha_2})...(1+p_k+...+p_k^{b\alpha_k}) (1+p1+...+p1bα1)(1+p2+...+p2bα2)...(1+pk+...+pkbαk)。所以可以先对 a a a进行质因子分解,然后问题变为怎么计算 1 + p + . . . + p k − 1 1+p+...+p^{k-1} 1+p+...+pk−1。设 f ( k ) = 1 + p + . . . + p k − 1 f(k)=1+p+...+p^{k-1} f(k)=1+p+...+pk−1,如果 k k k是偶数,则 f ( k ) = ( 1 + p + . . . + p k 2 − 1 ) + ( p k 2 + p k 2 + 1 + . . . + p k − 1 ) = ( 1 + p k 2 ) ( 1 + p + . . . + p k 2 − 1 ) = ( 1 + p k 2 ) f ( k 2 ) f(k)=(1+p+...+p^{\frac{k}{2}-1})+(p^{\frac{k}{2}}+p^{\frac{k}{2}+1}+...+p^{k-1})\\=(1+p^{\frac{k}{2}})(1+p+...+p^{\frac{k}{2}-1})=(1+p^{\frac{k}{2}})f(\frac{k}{2}) f(k)=(1+p+...+p2k−1)+(p2k+p2k+1+...+pk−1)=(1+p2k)(1+p+...+p2k−1)=(1+p2k)f(2k)又有 f ( 1 ) = 1 f(1)=1 f(1)=1,所以问题转化为怎么求 p k 2 m o d 9901 p^{\frac{k}{2}}\mod 9901 p2kmod9901( 9901 9901 9901是素数),这可以用快速幂来求,参考https://blog.csdn.net/qq_46105170/article/details/113823747。如果 k k k是奇数,那么 k − 1 k-1 k−1是偶数,有 f ( k ) = 1 + p ( 1 + p + . . . + p k − 2 ) = 1 + p f ( k − 1 ) f(k)=1+p(1+p+...+p^{k-2})=1+pf(k-1) f(k)=1+p(1+p+...+pk−2)=1+pf(k−1)就转化为已解决的问题了。代码如下:
#include <iostream>
#include <cstring>
using namespace std;
const int MOD = 9901;
// 快速幂
int qmi(int a, int k) {
a %= MOD;
int res = 1;
while (k) {
if (k & 1) res = res * a % MOD;
a = a * a % MOD;
k >>= 1;
}
return res;
}
int sum(int p, int k) {
if (k == 1) return 1;
if (k % 2 == 0) return (1 + qmi(p, k >> 1)) * sum(p, k >> 1) % MOD;
return (sum(p, k - 1) + qmi(p, k - 1)) % MOD;
}
int main() {
int a, b;
scanf("%d%d", &a, &b);
int res = 1;
for (int i = 2; i <= a / i; i++)
if (a % i == 0) {
int cnt = 0;
while (a % i == 0) {
cnt++;
a /= i;
}
res = res * sum(i, b * cnt + 1) % MOD;
}
if (a > 1) res = res * sum(a, b + 1) % MOD;
if (a == 0) res = 0;
printf("%d\n", res);
return 0;
}
时间复杂度 O ( a + log 2 b ) O(\sqrt{a}+\log^2 b) O(a+log2b),空间 O ( log b ) O(\log b) O(logb)。