【ACWing】97. 约数之和

题目地址:

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 0a,b5×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+...+pk1。设 f ( k ) = 1 + p + . . . + p k − 1 f(k)=1+p+...+p^{k-1} f(k)=1+p+...+pk1,如果 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+...+p2k1)+(p2k+p2k+1+...+pk1)=(1+p2k)(1+p+...+p2k1)=(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 k1是偶数,有 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+...+pk2)=1+pf(k1)就转化为已解决的问题了。代码如下:

#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)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值