zznuoj2094正约数之和

2094 : 正约数之和

时间限制:1 Sec 内存限制:128 MiB
提交:267 答案正确:93

提交 状态 讨论区

题目描述

我们把f(i)表示为i的正约数的和,而我们要求的是1<=i<=n之间所有i的f(i)之和!

输入


先输入一个正整数T,表示T个这是数据。T(T<=50)
每行输入一个正整数n。(n<10^6)

输出

输出一个数字,表示所求的数。

样例输入

复制
3
5
12
2018

样例输出

复制
21
127
3350309

思路:首先了解一下约数定理,

约数个数定理

编辑
对于一个大于1正整数n可以 分解质因数:
则n的 正约数的个数就是

定理简证

编辑
首先同上,n可以 分解质因数:n=p1^a1×p2^a2×p3^a3*…*pk^ak,
由约数定义可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1 ,共(a1+1)个;同理p2^a2的 约数有(a2+1)个......pk^ak的约数有(ak+1)个。
故根据 乘法原理:n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)。
其中a 1、a 2、a 3…a k是p 1、p 2、p 3,…p k的指数。
约数和定理:

    对于一个数n,它的约数和 f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)

综上可知(其实我也不知道怎么就得出来了,大概记住就行了):
对于一个数n,1-n的约数个数和为
 floor(n/i),其约数和为n - 1 + ∑floor(n/i)*i
ok,现在来看代码(其实这就很容易写了):
#include
#define ll long long
int main()
{
 int t,n;
 ll ans;
 scanf("%d",&t);
 while (t--)
 {
  scanf("%d",&n);
  ans = n;
  for (int i = 2;i <= n;i ++)
   ans += (n / i) * i;
  printf("%lld\n",ans);
 }
 return 0;
}


你可能感兴趣的:(zznuoj2094正约数之和)