NYOJ 928 小M的因子和(数论)

小M的因子和

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 2
描述

小M在上课时有些得意忘形,老师想出道题目难住他。小M听说是求因子和,还是非常得意,但是看完题目是求A的B次方的因子和,有些手足无措了,你能解决这个问题吗?

输入
有多组测试样例
每行两个数 A ,B ,(1≤A,B≤10^9) 
输出
输出A的B次方的因子和,并对9901取余。
样例输入
2 3
样例输出
15


分析:对A进行质因数分解,假设A = (p1^a1) * (p2^a2)*……*(pk^ak),假设A的因子和为sum,

则sum=(1 + p1 + p1^2 + ……+p1^a1)*(1+p2+p2^2 + ……+p2^a2)*……*(1+pk+pk^2+……+pk^ak),把这个式子展开之后.每一项刚好是A的因子。

所以求A^B的因子和时,只需把ai 改为ai*b,然后再求解即可。求得时候因为次方比较大,要用分治和快速幂来求。

#include <cstdio>
#include <cmath>
const int mod = 9901;

int Pow(int a, int n) {  //快速幂求a^n
    int res = 1;
    a %= mod;
    while(n) {
        if(n&1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

int get_sum(int a, int n) {  //求(1 + a + a^2 + …… + a^n)
    if(n == 0) return 1;
    if(n&1) return get_sum(a, n / 2) * (Pow(a, (n / 2 + 1)) + 1) % mod;
    else return (get_sum(a, n / 2 - 1) * (Pow(a, n / 2) + 1) + Pow(a, n)) % mod;
}

int main() {
    int a, b;
    while(~scanf("%d%d", &a, &b)) {
        int ans = 1;
        int m = (int)sqrt(a + 0.5);
        for(int i = 2; i <= m; ++i) {
            if(a % i == 0) {
                int k = 0;
                while(a % i == 0) {
                    k++;
                    a /= i;
                }
                ans = ans * get_sum(i, k * b) % mod;
            }
        }
        if(a > 1) ans = ans * get_sum(a, b) % mod;
        printf("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(数学)