Bootstrap

【约数之和】

题目

TLE代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define x first
#define y second

const int N = 5e7+10;
const int MOD = 9901; 
LL a, b;
unordered_map<int, int> cnt;
LL res = 1;
LL fast(int base, int expo)
{
    LL result = 1;
    while(expo)
    {
        if(expo & 1)
        {
            result *= base;
        }
        base *= base;
        expo /= 2;
    }
    
    return result;
}
LL cal(int p, int k)
{
    if(k == 0) return 0;
    if(k == 1) return 1;
    if(k == 2) return p + 1;
    
    if(k%2 == 0) return (fast(p, k/2) + 1) * cal(p, k/2);
    else return cal(p, k-1) + fast(p, k-1);
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    cin >> a >> b;
    
    int num = a;
    while(num%2 == 0) cnt[2]++, num /= 2;
    for(int i = 3; i <= a; i+=2)
    {
        bool flag = true;
        for(int j = 2; j*j <= i; j++)
        {
            if(i%j==0)
            {
                flag = false;
                break;
            }
        }
        if(flag)
        {
            if(num%i == 0)
            {
                while(num%i == 0) cnt[i]++, num /= i;
            }
        }

    }
    
    for(auto const & m : cnt)
    {
        res *= cal(m.x, m.y*b + 1);
    }
    
    cout << res % MOD << '\n';
}

错误分析

1.        质因数分解写太蠢,从最小的因数开始分解就能保证分解出的因数全部是质数,不需要先筛质数再判定因数。

2.        质因数分解也忘了考虑a > 1的情况,这对应唯一质因数就是自己

正确代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int MOD = 9901;
LL a, b, res = 1;

LL fast_power(LL base, LL expo)
{
    LL result = 1;
    while(expo)
    {
        if(expo & 1) result = result * base % MOD;
        base = base * base % MOD;
        expo >>= 1;
    }
    return result;
}
LL sum(LL p, LL k)
{
    if(k == 0) return 0;
    else if(k == 1) return 1;
    else if(k == 2) return p + 1;
    
    if(k % 2 == 0) return (fast_power(p, k/2) + 1) * sum(p, k/2) % MOD;
    else return (sum(p, k-1) + fast_power(p, k-1)) % MOD;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    cin >> a >> b;
    for(int i = 2; i*i <= a; i++)
    {
        if(a % i == 0)
        {
            int cnt = 0;
            while(a % i == 0)
            {
                cnt++;
                a /= i;
            }
            
            res = res * sum(i, cnt*b+1) % MOD;
        }
    }
    
    if(a > 1) res = res * sum(a, 1*b+1) % MOD;
    if(!a) res = 0;
    
    cout << res % MOD <<  "\n";
}

感悟

1.        遇到大数据全部开LL,除了循环指针

2.        存在mod时,更新不能用*= 要老实写

3.        &1既是判定快速幂是否操作,也是判定奇数

4.        虽然a > 1代表自己是质因数,但是a是个变化量,a可能不是最开始的a,res也不是最开始的1,有其他因数

疑惑

快速幂用MOD为啥不影响结果,这是恒等变换吗????

;