POJ 1845 【数论】

题目链接:POJ 1845

题意

ab a b 的所有约数之和,最终结果对9901求模

需要知识

1、快速幂:二分法求 nm n m 的结果
2、因数分解:遍历求出所有因数
3、约数和定理:假设n= p1a1p2a2...pnan p 1 a 1 ∗ p 2 a 2 ∗ . . . p n a n , 其中 pi p i 都是素数,
那么n的约束之和f(n)= (1+p11+...p1a1)(1+p21+...p2a2)...(1+pn1+...pnan) ( 1 + p 1 1 + . . . p 1 a 1 ) ∗ ( 1 + p 2 1 + . . . p 2 a 2 ) . . . ( 1 + p n 1 + . . . p n a n )

题目分析

题目是求 ab a b 的约数之和,那么假设a= p1a1p2a2...pnan p 1 a 1 ∗ p 2 a 2 ∗ . . . p n a n
ab a b = (p1a1p2a2...pnan)b ( p 1 a 1 ∗ p 2 a 2 ∗ . . . p n a n ) b = p1a1bp2a2b...pnanb p 1 a 1 ∗ b ∗ p 2 a 2 ∗ b ∗ . . . p n a n ∗ b
从约数和定理可知, ab a b 的约数之和 f( ab a b ) = (1+p11+...p1a1b)(1+p21+...p2a2b)...(1+pn1+...pnanb) ( 1 + p 1 1 + . . . p 1 a 1 ∗ b ) ∗ ( 1 + p 2 1 + . . . p 2 a 2 ∗ b ) . . . ( 1 + p n 1 + . . . p n a n ∗ b ) .

回到一般情况,这样就转化成求 1+p1+...pn 1 + p 1 + . . . p n .
假设n是奇数,则一共有偶数项,此时 1+p1+...pn 1 + p 1 + . . . p n = (1+pn2+1)(1+p1+...pn2) ( 1 + p n 2 + 1 ) ∗ ( 1 + p 1 + . . . p n 2 ) .
例如n = 5时, 1+p1+p2+p3+p4+p5 1 + p 1 + p 2 + p 3 + p 4 + p 5 = (1+p3)(1+p+p2) ( 1 + p 3 ) ( 1 + p + p 2 )

假设n是偶数,则一共有奇数项,这个时候我们将最后一项单独计算,剩下的就是偶数项,可以按照上面的方法进行计算。
此时 1+p1+...pn 1 + p 1 + . . . p n = (1+pn2)(1+p1+...pn21)+pn ( 1 + p n 2 ) ∗ ( 1 + p 1 + . . . p n 2 − 1 ) + p n
例如n = 6时, 1+p1+p2+p3+p4+p5+p6 1 + p 1 + p 2 + p 3 + p 4 + p 5 + p 6 = (1+p3)(1+p+p2)+p6 ( 1 + p 3 ) ( 1 + p + p 2 ) + p 6
这样根据奇偶性递归下去即可求出 1+p1+...pn 1 + p 1 + . . . p n 的结果。

思路总结

假设a= p1a1p2a2...pnan p 1 a 1 ∗ p 2 a 2 ∗ . . . p n a n
ab=(p1a1p2a2...pnan)b a b = ( p 1 a 1 ∗ p 2 a 2 ∗ . . . p n a n ) b = p1a1bp2a2b...pnanb p 1 a 1 ∗ b ∗ p 2 a 2 ∗ b ∗ . . . p n a n ∗ b

(1)根据约数和定理,题目所有的结果转化成
(1+p11+...p1a1b)(1+p21+...p2a2b)...(1+pn1+...pnanb) ( 1 + p 1 1 + . . . p 1 a 1 ∗ b ) ∗ ( 1 + p 2 1 + . . . p 2 a 2 ∗ b ) . . . ( 1 + p n 1 + . . . p n a n ∗ b ) 的结果
(2)对于每项 pi p i ai a i ,求出 (1+pi1+pi2+...piaib) ( 1 + p i 1 + p i 2 + . . . p i a i ∗ b ) ,利用上面分析的奇偶性递归下去即可求出。
(3)相乘起来即为答案。

注意点

根据题目数据情况,数据类型要用long long int
如果a是素数需要特别判断

代码

#include <iostream>
#include <cstdio>
using namespace std;

typedef long long int LL;
const LL mod = 9901;

//二分求a的b次方
LL pow_mod(LL a, LL b){ 
    LL ret = 1;
    while(b != 0){
        if(b % 2 == 1){
            ret = (ret * a) % mod ;
        }
        a = (a * a ) % mod ;
        b /= 2;
    }
    return ret;
}
// 根据奇偶性求q的各次方之和
LL OneToN(LL q, LL n){
    if(n == 0)
        return 1;
    if(n % 2 == 1)
        return ( (1 + pow_mod(q,n/2+1) ) * OneToN(q,n/2) ) % mod;
    else 
        return ( (1 + pow_mod(q,n/2) ) * OneToN(q, n/2 - 1) + pow_mod(q,n)) % mod; 
}

int main(){
    LL a ,b;
    scanf("%lld %lld", &a , &b);
    LL ans = 1;
    LL n = a;
    // cnt 是指数, i 是底数
    for(LL i = 2 ; i * i <= n; i++){
        int cnt = 0;
        while(n % i == 0){
            cnt++;
            n /= i;
        }
        if(cnt != 0)
            ans = ( ans * OneToN(i, cnt * b) ) % mod;
    }
    // 特判
    if(n > 1)
        ans = ( ans * OneToN(n, b) ) % mod;
    printf("%lld\n",ans);
}
点赞