poj3604

题意:对于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)*……。这个多项式乘积的意思就是,每个括号中取一个,就是取了一定量的质因子,并获得了其约数个数的立方。相乘便得到了对应约数的约数个数。

View Code
#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;
}
原文地址:https://www.cnblogs.com/rainydays/p/2110330.html