zoukankan      html  css  js  c++  java
  • 约数和问题

    问题链接:https://ac.nowcoder.com/acm/contest/998/F

    题意:求ab的所有约数的和。

    知识点:数学(质因数分解、唯一分解定理、约数和公式)、分治递归。

    相关介绍:

    1. 唯一分解定理:每个大于1的自然数n均可分解为有限个素数之积,如不计素数在乘积中的顺序,那么这种分解方式是唯一的。并且n可以唯一写成p1a1p2a2p3a3……pnan
    2. 质因数分解:我们可以保证当n被升序的每一个数除到不能除时,其因数都是质数,具体证明见线性筛。
    3. 约数个数公式:由①中记法,我们记N为约数的个数,以p1a1为例,其p10……p1a1都是n的约数,于是就有a1+1个,同时根据乘法原理,则N = (a1 + 1)(a2 + 1)(a3 + 1)……(an + 1)
    4. 约数和公式:由③,我们相当于是做个一个排列,而对于每种情况,都是只取其中一种,不难发现,记S为所有约数之和,则S = (p10 + p11 + …… + p1a1)……(pn0  + pn1 + …… + pnan
    5. 由于是求的ab的约数之和,我们不妨先将a记作①中形式,那么对于①中的每个p,其指数都为a1*b。

    思路:

    1. 相关知识点都已经给出,我们的思路也不难得到,那就是通过分解a的质因数,然后求所有的质因数(注意加了b次方)之和。
    2. 注意在求解约数和时,我们采取的是一种递归的方法,因为我们可以做以下推导,得到递归思路,进而避免了不必要的计算。
    3. S(p,k) = p0 + p1 + …… + pk,其中p代表质因数,k代表其最高次方
    4. 当k为奇数时,S(p,k) = p0 + p1 + …… + pkp0 + p1 + …… + pk/2 - 1 + pk/2 + …… + pkp0 + p1 + …… + pk/2 - 1 + pk/2(p0 + p1 + …… + pk/2 - 1)  + pk = (1 + pk/2)S(p, k / 2)+ pk
    5. 当k为偶数时,也一样的推。

    总结:

    • 千万要注意运算符的优先级,k & 1 == 1与 (k & 1)== 1是不一样的!!!

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int mod = 9901;
     
    int qpow(int a, int b)
    {
        int res = 1;
        a %= mod;
        while(b)
        {
            if(b & 1)   res = res % mod * a % mod;
            a = a % mod * a % mod;
            b >>= 1;
        }
        return res % mod;
    }
    int sum(int p, int k)
    {
        if(k == 0)  return 1;
        else if(k % 2 == 0)
            return ((1 + qpow(p, k >> 1)) * sum(p, (k >> 1) - 1) + qpow(p, k)) % mod;
        else
            return ((1 + qpow(p, (k + 1) >> 1)) * sum(p, (k - 1) >> 1)) % mod;
    }
     
    int main()
    {
        ios::sync_with_stdio(false);
        int a, b;   cin >> a >> b;
        int ans = 1;
        for(int i = 2; i <= a; i++)
        {
            int s = 0;
            while(a % i == 0)
            {
                s++;
                a /= i;
            }
            if(s) ans = ans * sum(i, s * b) % mod;
        }
        if(a == 0)
            cout << 0 << endl;
        else
            cout << ans << endl;
        return 0;
    }
    

      

  • 相关阅读:
    Redis 学习(二十)服务器
    Redis 学习(十八)连接
    Redis学习(十七) 脚本
    Redis学习(十六)事务
    Redis学习(十四) 发布订阅
    python中如何使用requests模块下载文件并获取进度提示?
    Python实例获取mp3文件的tag信息
    python 视频处理,提取视频相关帧,读取Excel
    爬虫数据采集技术趋势-智能化解析
    Python中文转拼音代码(支持全拼和首字母缩写)
  • 原文地址:https://www.cnblogs.com/ACM-Epoch/p/13342227.html
Copyright © 2011-2022 走看看