题目描述
我们把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
刚开是想,对于一个数n,遍历1~n 找它的约数,这样子有太多多余的查找,果然超时了,
其实是可以不用遍历去查找,可以直接找到一个数的约数,
比如: dp[ i*j ] , i 和 j 就是 i*j 的约数啊~~~~~
用一个双循环,因为约数是成对出现的,,而且 i==j 的时候,只需要加一次,比如 4的约数和 = 1 +2 +4 = 7
所以,双循环中 dp[ i*j ] += j; 最后加 i 或 j 无所谓。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int maxn = 1e6+5; LL dp[maxn]; void init() { memset(dp,0,sizeof(dp)); for(int i = 1;i<maxn;i++) //每个数的约数和 { for(int j = 1;j*i<maxn;j++) { dp[i*j] += j; //最后加 i 或 j 无所谓 } } for(int i = 1;i<maxn;i++) // 1-n 每个数的约数和的 和 dp[i] = dp[i-1] + dp[i]; } int main() { init(); int t,a; scanf("%d",&t); while(t--) { scanf("%d",&a); printf("%lld\n",dp[a]); } return 0; }