1. 程式人生 > 實用技巧 >題解 洛谷P1593 因子和

題解 洛谷P1593 因子和

題目描述

給定 \(a,b\) ,求 \(a^b\) 的約數之和。

\(1\leq a,b \leq 5\times 10^7\)

答案對 \(9907\) 取模。

Solution

先把 \(a\) 分解質因數,假設分解後的柿子是 \(p_1^{a_1}p_2^{a_2}p_3^{a_3}\cdots\cdots p_k^{c_k}\)

然後 \(a^b\) 的質因數分解的柿子就是

\[p_1^{a_1\times b}p_2^{a_2\times b}p_3^{a_3\times b}\cdots\cdots p_k^{c_k\times b} \]

根據約數求和公式,我們可以得到 \(a^b\)

的約數和是:

\[(1+p_1+p_1^2+\cdots+p_1^{a_1\times b})\times(1+p_2+p_2^2+\cdots+p_2^{a_2\times b})\times\cdots\times(1+p_k^{1}+p_k^{2}+\cdots+p_k^{c_k\times b}) \]

然後考慮如何求出 \((1+p_i+p_i^2+\cdots+p_i^{a_i\times b})\)

方法 1 :分治

為了更加簡便,我們約定這裡要求的柿子是: \((1+p+p^2+\cdots+p^k)\)

同時我們約定: \(f(p,k) = (1+p+p^2+\cdots+p^k)\)

這裡分兩種情況討論:

  • \(k\) 是奇數,那麼原柿子可以化成:

\[(1+p+p^2+\cdots+p^\frac{k-1}{2})+(p^\frac{k+1}{2}+\cdots+p^k)\\ =f(p,\frac{k-1}{2})+p^\frac{k+1}{2}\times(1+p+p^2+\cdots+p^\frac{k-1}{2}) \\ =f(p,\frac{k-1}{2})+p^\frac{k+1}{2}\times f(p,\frac{k-1}{2}) \\ = (1 + p ^\frac{k+1}{2})\times f(p ,\frac{k-1}{2}) \]

  • \(k\)
    是偶數,那麼我們考慮轉換成奇數:

\[1+(p+p^2+\cdots+p^k) \\ =1+p\times(1+p+p^2+\cdots+p^{k-1})\\ =1+p\times f(p,k-1) \]

注意取模。

完整程式碼如下

#include <cstdio>
#include <cstring>
#define int long long
const int mod = 9901;
inline int pow(int a ,int b) {
    int ans = 1;
    while (b) {
        if (b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
inline int f(int p ,int k) {
    if (k == 0) return 1;
    if (k & 1)
        return ((1 + pow(p ,(k + 1) >> 1)) % mod) * f(p ,(k - 1) >> 1) % mod;
    return (1 + p * f(p ,k - 1) % mod) % mod;
}
int a ,b ,ans = 1;
signed main() {
    scanf("%lld%lld" ,&a ,&b);
    if (a == 0) return puts("0") ,0; //這裡記得特判一下 a = 0 ,很坑
    for (int i = 2;i * i <= a; i++)
        if (a % i == 0) {
            int s = 0;
            while (a % i == 0) s++ ,a /= i;
            ans = ans * f(i ,s * b) % mod;
        }
    if (a > 1) ans = ans * f(a ,b) % mod;
    printf("%lld\n" ,ans);
    return 0;
}