Sumdiv

2023-12-13 06:24:45

title: Sumdiv
date: 2023-12-12 21:45:09
tags: 分治
categories: 算法进阶指南

题目大意

A B A^B AB 的所有约数之和 m o d mod mod 9901 9901 9901( 1 1 1 ≤ \leq A , B A,B A,B ≤ \leq 5 ? 1 0 7 5 * 10 ^ 7 5?107)

解题思路

A A A 分解质因数,表示为 p 1 c 1 p1^{c_1} p1c1? * p 2 c 2 p2 ^ {c_2} p2c2? * …… * p n c n pn^{c_n} pncn?,那个 A ? B A * B A?B 就为 p 1 B ? c 1 p1^{B * c_1} p1B?c1? * p 2 B ? c 2 p2 ^ {B * c_2} p2B?c2? * …… * p n B ? c n pn^{B * c_n} pnB?cn?
根据乘法分配律, A B A^B AB 所有约数的和就是:
( 1 + p 1 + … … + p 1 B ? c 1 1 + p_1 + …… + p_1^{B * c_1} 1+p1?+……+p1B?c1??) * ( 1 + p 2 + … … + p n B ? c 2 1 + p_2 + …… + p_n^{B * c_2} 1+p2?+……+pnB?c2??) * …… * ( 1 + p n + … … + p n B ? c n 1 + p_n + …… + p_n^{B * c_n} 1+pn?+……+pnB?cn??)
比如: 360 360 360 = 2 3 ? 3 2 ? 5 1 2^3*3^2*5^1 23?32?51,约数之和为 ( 2 0 + 2 1 + 2 2 + 2 3 ) ? ( 3 0 + 3 1 + 3 2 ) ? ( 5 0 + 5 1 ) (2^0 + 2^1 + 2^2 + 2 ^ 3) * (3 ^ 0 + 3 ^ 1 + 3 ^ 2) * (5 ^ 0 + 5 ^ 1) (20+21+22+23)?(30+31+32)?(50+51)
约数个数为 ( 3 + 1 ) ? ( 2 + 1 ) ? ( 1 + 1 ) (3 + 1) * (2 + 1) * (1 + 1) (3+1)?(2+1)?(1+1)
每一个括号都是等比数列,使用分治法进行等比数列的求和。
问题转化为:
使用分治法求 sum(p,c) = 1 + p + p 2 + … … + p c 1 + p + p ^ 2 + …… + p ^ c 1+p+p2+……+pc = ?
c c c 为奇数:sum(p,c) = (1 + p c + 1 p^{c + 1} pc+1) * sum(p,(c - 1) / 2);
c c c 为偶数:sum(p,c) = (1 + p c / 2 p ^ {c /2 } pc/2) * sum(p,c / 2 - 1) + p c p ^ c pc;
每一次分治之后,问题的规模会缩小一半,配合快速幂即可在 O ( l o g c ) O(log c) O(logc) 的时间内求出等比数列的和。

代码实现

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

typedef long long LL;

const int N = 1314;

const int MOD = 9901;

LL kmi(LL a,LL k)
{
	LL ans = 1;
    a %= MOD;
	for(;k ; k >>= 1){
		if(k & 1){
			ans = ans * a % MOD; 
		}
		a = a * a % MOD;
	}
	return ans;
}

LL sum(LL p,LL c)
{
    if(c == 0) return 1; 
	else if(c & 1){
		return (1 + kmi(p,(c + 1) / 2) % MOD) * sum(p,(c - 1) / 2) % MOD;
	}
	else{
		return (1 + kmi(p,c / 2)) % MOD * sum(p,c / 2 - 1)  % MOD+ kmi(p,c) % MOD;
	}
}

unordered_map<LL,LL> cnt;
int main()
{
	LL A,B;
	cin >> A >> B;
	
	for(int i = 2; i <= A / 2 ; i ++){
		while(A % i == 0){
			A /= i;
			cnt[i] ++; 
		}
	}
	if(A == 0){
        cout << 0 << endl;
        return 0;
    }
	if(A > 1) cnt[A] ++;
	LL ans = 1;
	for(auto x : cnt){
       // cout << x.first << ' ' << x.second << endl;
		ans *= sum(x.first,x.second * B);
		ans %= MOD;
	}
	cout << ans  << endl;
}

文章来源:https://blog.csdn.net/m0_73865722/article/details/134961682
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。