--- title: "约数之和" created: 2025-11-28 tags: - 算法 --- # 约数之和 ## 题目 [约数之和](https://www.acwing.com/problem/content/873/) ![[image-a979a6f7.png]] ## 思路分析 沿用上一题的思想 把一个数N 写成:$N = (p1^{x1})(p2^{x2})(p3^{x3})…(pk^{xk})$,其中pi为质数。 则N的约数个数为:$(x1+1)(x2+1)(x3+1)…(xk+1)$ 那这N个约数的和其实就是($p1^0+p1^1+……+p1^{x1})……(Pk^0+pk^1+……+pk^{xk})$ 还是拿这个例子 例如:12 的质因子有 2,3 12的约数有:1,2,3,4,6,12 约数1 是由 0 个 2, 0 个3相乘得到的 约数2 是由 1 个 2, 0 个3相乘得到的 约数3 是由 0 个 2, 1 个3相乘得到的 约数4 是由 2 个 2, 0 个3相乘得到的 约数6 是由 1 个 2, 1 个3相乘得到的 约数12 是由 2 个 2, 1 个3相乘得到的 12 可以分解为:$2^2\*3^1$ 那么约数之和 应该是$(2^0+2^1+2^2)(3^0+3^1)=7\*4=28$ 等价于 1+2+3+4+6+12=28 证明: ![[image-6b3cf439.png]] 记忆的话 先拆出所有质因数 对每一个基数都从 0到指数 累加一遍 然后相乘 ## 代码实现 ```cpp #include using namespace std; typedef long long LL; const int mod=1e9+7; unordered_map weight; int T; int main() { cin>>T; while(T--){ int n;cin>>n; for(int i=2;i<=n/i;i++){ while(n%i==0){ weight[i]++; n/=i; } } if(n>1) weight[n]++; } LL res=1; for(auto prime:weight){ int base=prime.first,index=prime.second; LL temp=1,sum=1; while(index--){ temp=temp*base%mod; sum=(sum+temp)%mod; } res=res*sum%mod; } cout<::__type {aka double} */ //pow函数返回一个 double 类型的结果,与 mod(一个 int 类型)进行取模会冲突 //C++ 中没有为浮点数定义取模运算符 % //要改进的话 其实就可以牵扯到快速幂算法了 (负改进emm) #include using namespace std; typedef long long LL; const int mod=1e9+7; unordered_map weight; int T; // 快速幂算法,计算 (base^exponent) % mod LL modPow(LL base, LL exponent, LL modulus) { base %= modulus; LL result = 1; while (exponent > 0) { if (exponent % 2 == 1) result = (result * base) % modulus; base = (base * base) % modulus; exponent >>= 1; } return result; } int main() { cin>>T; while(T--){ int n;cin>>n; for(int i=2;i<=n/i;i++){ while(n%i==0){ weight[i]++; n/=i; } } if(n>1) weight[n]++; } LL res=1; for(auto prime:weight){ int base=prime.first,index=prime.second; LL sum=0; for(int i=0;i<=index;i++){ sum = (sum + modPow(base, i, mod)) % mod; } res=res*sum%mod; } cout< using namespace std; typedef long long LL; const int mod=1e9+7; unordered_map weight; int T; int main() { cin>>T; while(T--){ int n;cin>>n; for(int i=2;i<=n/i;i++){ while(n%i==0){ weight[i]++; n/=i; } } if(n>1) weight[n]++; } LL res=1; for(auto prime:weight){ int base=prime.first,index=prime.second; LL temp=1; while(index--){ temp=(temp*base+1)%mod; } res=res*temp%mod; } cout<