Sumdiv(数论,快速幂)

Sumdiv
题意:给出两个数 n , m n,m nm,求 n m n^m nm的全部因子的和 S S S 9901 9901 9901取模的结果。

结论:
1. 唯 一 分 解 定 理 : 1.唯一分解定理: 1.
任 意 自 然 数 都 可 以 拆 成 质 因 子 乘 积 的 形 式 , n m = a 1 b 1 ∗ m ∗ a 2 b 2 ∗ m . . . ∗ a n b k ∗ m , 其 中 a 1 , a 2 . . . a k 都 是 n 的 质 因 子 , 例 如 396 = 2 2 ∗ 3 2 ∗ 1 1 1 任意自然数都可以拆成质因子乘积的形式,n^m = {a_1}^{b_1*m}*{a_2}^{b_2*m}...*{a_n}^{b_k*m},\quad其中a_1,a_2...a_k都是n的质因子,例如396 = 2^2*3^2*11^1 nm=a1b1ma2b2m...anbkm,a1,a2...akn,396=2232111

2. 利 用 结 论 1 和 排 列 组 合 知 识 ( 在 第 i 个 质 因 子 中 选 [ 0 , b i ] 个 ) : 2.利用结论1和排列组合知识(在第i个质因子中选[0,b_i]个): 2.1(i[0,bi]):
我 们 有 结 论 2 求 n m 的 全 部 因 子 的 和 S = ∏ i = 1 k ∑ j = 1 b i ∗ m a j , 将 S 拆 开 就 是 S = ( 1 + a 1 1 . . . + a 1 b 1 ∗ m ) ∗ ( 1 + a 2 1 . . . + a 2 b 2 ∗ m ) . . . ∗ ( 1 + a k 1 . . . + a k b k ∗ m ) 我们有结论2求n^m的全部因子的和S=\prod_{i=1}^k\sum_{j=1}^{b_i*m}{a^j} ,\quad将S拆开就是S=(1+{a_1}^1...+{a_1}^{b_1*m})*(1+{a_2}^1...+{a_2}^{b_2*m})...*(1+{a_k}^1...+{a_k}^{b_k*m}) 2nmS=i=1kj=1bimaj,SS=(1+a11...+a1b1m)(1+a21...+a2b2m)...(1+ak1...+akbkm)

3. 等 比 数 列 的 求 法 : 分 治 3.等比数列的求法:分治 3.:
T = 1 + a + a 2 . . . + a n T= 1+a+a^2...+a^n T=1+a+a2...+an
如 果 n 是 奇 数 的 话 T = ( 1 + a + a 2 . . . + a n / 2 ) ∗ ( 1 + a n / 2 + 1 ) 如果n是奇数的话T=(1+a+a^2...+a^{n/2})*(1+a^{n/2+1}) nT=(1+a+a2...+an/2)(1+an/2+1)
如 果 n 是 偶 数 的 话 T = ( 1 + a + a 2 . . . + a n / 2 − 1 ) ∗ ( 1 + a n / 2 + 1 + a ) + a n / 2 如果n是偶数的话T=(1+a+a^2...+a^{n/2-1})*(1+a^{n/2+1}+a)+a^{n/2} nT=(1+a+a2...+an/21)(1+an/2+1+a)+an/2

思路:利用结论 1 , 2 , 3 1,2,3 123求出结果,求 n m n^m nm的全部因子的和并在求的过程中不断取模。

C o d e Code Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 9901;
map<ll, ll> M;//记录质因子的次数
//快速幂
ll qpow(ll a, ll b) {
    
    
    ll ans = 1, res = a;
    while(b) {
    
    
        if(b & 1) ans = ans * res % mod;
        res = res * res % mod;
        b >>= 1;
    }
    return ans;
}
//等比数列求和
ll faction(ll a, ll b) {
    
    
    if(b == 0) return 1;
    if(b & 1) return faction(a, b/2)*(1+qpow(a, b/2+1)) % mod;
    else return (faction(a, b/2-1)*(1+qpow(a, b/2+1)) + qpow(a, b/2))% mod;
}

int main() {
    
    
    ll n, m, ans = 1;
    cin >> n >> m;
    //特判
    if(n == 0) cout << 0;
    else if(m == 0 || n == 1) cout << 1;
    else {
    
    
    	//找到所有质因子。
        for(int i=2; i*i<=n; ) {
    
    
            while(!(n%i)) M[i]++, n/=i;
            if(i == 2) i++;
            else i += 2;
        }
        if(n != 1) M[n] = 1;//特判:n本来就是质数
        for(map<ll, ll>::iterator it = M.begin(); it != M.end(); it++) {
    
    
            ll a = it->first, b = it->second * m;
            ans = ans * faction(a, b) % mod;//边乘边取模。
        }
        cout << ans % mod;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45363113/article/details/108112519