当前位置 博文首页 > ttoobne:AcWing 97. 约数之和 (费马小定理 / 矩阵快速幂 / 分

    ttoobne:AcWing 97. 约数之和 (费马小定理 / 矩阵快速幂 / 分

    作者:[db:作者] 时间:2021-08-30 10:35

    题目链接

    一个数 A 的约数之和可以由分解质因数求得,一个质因数 p 在 A 中出现 c 次,那么对于一个约数 X ,X 中 p 出现的次数一定为 0次 ~ c次,所以对于每个 p 可以构造一个等比数列 1 + p + p^2 + p^3 + ...... +p^c,最后将所有的等比数列之和乘起来即可。即 ans = ans * sum(p[i], c[p[i]]) %?mod; 其中 p[i] 为 A 的质因数, c[p[i]] 为 p[i] 在 A 中出现的次数, sum为首项为 1 ,尾项为 (p[i] ^ c[p[i]]) 的等比数列求和函数。

    那么 A的B次方 求约数之和就是在原来每个质因数出现的次数乘上 B 即可。

    接下来是三种作法:

    1. 费马小定理。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    #define int ll
    #define PI acos(-1.0)
    #define INF 0x3f3f3f3f3f3f3f3f
    #define P pair<int, int>
    #define fir first
    #define sec second
    #define fastio ios::sync_with_stdio(false), cin.tie(0)
    const int mod = 9901;
    const int MAXM = 50000 + 10;
    const int MAXN = 1000000 + 10;
    
    int a, b;
    int p[MAXN], c[MAXN], cnt;
    
    int POW(int n, int m)
    {
        int ans = 1;
        while(m) {
            if(m & 1) ans = ans * n % mod;
            n = n * n % mod;
            m >>= 1;
        }
        return ans % mod;
    }
    
    void deal()
    {
        for(int i = 2; i <= a; i ++) {
            if(a % i == 0) {
                p[cnt++] = i;
                while(a % i == 0) {
                    a /= i;
                    c[i] ++;
                }
            }
        }
    }
    
    signed main()
    {
        cin >> a >> b;
        if(a == 0) {
            cout << 0 << endl;
            return 0;
        }
        deal();
        int ans = 1;
        for(int i = 0; i < cnt; i ++) {
            if(p[i] - 1 % mod == 0) {
                ans = ans * (b * c[p[i]] + 1) % mod;
            }
            else {
                ans = ans * ((POW(p[i], b * c[p[i]] + 1) - 1 + mod) % mod) * (POW(p[i] - 1, mod - 2)) % mod;
            }
        }
        cout << ans << endl;
    }

    2. 矩阵快速幂

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    #define int ll
    #define PI acos(-1.0)
    #define INF 0x3f3f3f3f3f3f3f3f
    #define P pair<int, int>
    #define fir first
    #define sec second
    #define fastio ios::sync_with_stdio(false), cin.tie(0)
    const int mod = 9901;
    const int M = 2 + 10;
    const int N = 1000000 + 10;
    
    int a, b;
    int p[N], c[N], cnt;
    
    void deal()
    {
        for(int i = 2; i <= a; i ++) {
            if(a % i == 0) {
                p[cnt++] = i;
                while(a % i == 0) {
                    a /= i;
                    c[i] ++;
                }
            }
        }
    }
    
    struct Mat {
        int n;
        int m[M][M];
    };
    Mat operator *(Mat a,Mat b)
    {
        int n = 2;
        Mat c;
        memset(c.m, 0, sizeof c.m);
        for(int k = 0; k < n; k ++){
            for(int i = 0; i < n; i ++){
                if(a.m[i][k])
                    for(int j = 0; j < n; j ++)
                        if(b.m[k][j])
                            c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
            }
        }
        return c;
    }
    Mat operator ^(Mat a, int k)
    {
        int n = 2;
        Mat c;
        memset(c.m, 0, sizeof c.m);
        for(int i = 0; i < n; i ++){
            c.m[i][i] = 1;
        }
        for(; k; k >>= 1)
        {
            if(k&1) c = c * a;
            a = a * a;
        }
        return c;
    }
    
    signed main()
    {
        cin >> a >> b;
        if(a == 0) {
            cout << 0 << endl;
            return 0;
        }
        deal();
        int ans = 1;
        for(int i = 0; i < cnt; i ++) {
            Mat start, ed, mid;
            
            mid.m[0][0] = 1; mid.m[0][1] = 0;
            mid.m[1][0] = p[i]; mid.m[1][1] = p[i];
            
            start.m[0][0] = 1; start.m[0][1] = 1;
            
            ed = start * (mid ^ (c[p[i]] * b));
            ans = ans * ed.m[0][0] % mod;
        }
        cout << ans << endl;
    }

    ?

    3. 分治

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    #define int ll
    #define PI acos(-1.0)
    #define INF 0x3f3f3f3f3f3f3f3f
    #define P pair<int, int>
    #define fir first
    #define sec second
    #define fastio ios::sync_with_stdio(false), cin.tie(0)
    const int mod = 9901;
    const int M = 2 + 10;
    const int N = 1000000 + 10;
    
    int a, b;
    int p[N], c[N], cnt;
    
    void deal()
    {
        for(int i = 2; i <= a; i ++) {
            if(a % i == 0) {
                p[cnt++] = i;
                while(a % i == 0) {
                    a /= i;
                    c[i] ++;
                }
            }
        }
    }
    
    int POW(int n, int m)
    {
        int ans = 1;
        while(m) {
            if(m & 1) ans = ans * n % mod;
            n = n * n % mod;
            m >>= 1;
        }
        return ans % mod;
    }
    
    int divide(int q, int n)
    {
        if(n == 0) return 1;
        if(n & 1) {
            return (1 + POW(q, (n + 1) / 2)) * divide(q, (n - 1) / 2) % mod;
        }
        else {
            return (POW(q, n) + (1 + POW(q, n / 2)) * divide(q, (n - 2) / 2)) % mod;
        }
    }
    
    signed main()
    {
        cin >> a >> b;
        if(a == 0) {
            cout << 0 << endl;
            return 0;
        }
        deal();
        int ans = 1;
        for(int i = 0; i < cnt; i ++) {
            ans = ans * divide(p[i], c[p[i]] * b) % mod;
        }
        cout << ans << endl;
    }

    ?

    cs