题意:对于n的每个约数a,设a的约数个数为b,求所有b^3的和。
分析:我们可以试想,对于一个整数n=a^k(a是质数)n的约数个数一定是k+1,这些约数是a^0,a^1,a^2……。而我们发现每个约数仍然是a^k的形式,所以每个约数的约数个数一定为ki+1(对于约数a^i)。所以约数个数序列应该为1,2,3,4,5……k+1。而对于这个n本题所求的结果一定为1^3,2^3……(k+1)^3。用立方和公式可直接求解。立方和公式:[n*(n+1)/2]^2。当然,本题给出的数可能由多个质因子组成。而这样一来,n的约数就变为a^i * b^j * c^k ……(a,b,c为质因子)。而每个约数的约数个数也符合相乘的规律,即对于约数a^i * b^j * c^k ……,其约数个数应为:a^i的约数个数*b^j的约数个数*c^k的约数个数。(因为其每个约数都是分别取a^i的一个约数、b^j的一个约数……并相乘得到的,因此根据组合数学的乘法原理,总方法数等于每个步骤的方法数相乘)这样题目就可以转化为,每个质因子取若干个,并将其乘积的约数个数(每个的约数个数相乘)取立方,并求所有情况的和。也就是把每个质因子取若干个,并把其的方法数取立方后相乘,然后求总和。这样就可以提取后写成多项式乘积的形式了:(1^3+2^3 + ……+(i+1)^3)*(1^3+2^3 + ……+(j+1)^3)*(1^3+2^3 + ……+(k+1)^3)*……。这个多项式乘积的意思就是,每个括号中取一个,就是取了一定量的质因子,并获得了其约数个数的立方。相乘便得到了对应约数的约数个数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
usingnamespace std;
#define maxn 5000005
#define maxm 1000000
boolis[maxn];
int prm[maxm];
int n;
int getprm(int n)
{
int i, j, k =0;
int s, e = (int) (sqrt(0.0+ n) +1);
memset(is, 1, sizeof(is));
prm[k++] =2;
is[0] =is[1] =0;
for (i =4; i < n; i +=2)
is[i] =0;
for (i =3; i < e; i +=2)
if (is[i])
{
prm[k++] = i;
for (s = i *2, j = i * i; j < n; j += s)
is[j] =0;
}
for (; i < n; i+=2)
if (is[i])
prm[k++] = i;
return k;
}
int main()
{
//freopen("t.txt", "r", stdin);
int tot = getprm(maxn);
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
longlong ans =1;
for (int i =0; prm[i] * prm[i] <= n && i < tot; i++)
{
longlong d =0;
while (n % prm[i] ==0)
{
n /= prm[i];
d++;
}
ans *= (d +1) * (d +2) /2;
ans *= (d +1) * (d +2) /2;
}
if (n !=1)
ans *=9;
printf("%lld\n", ans);
}
return0;
}