1. 暴力拆解
n为所要处理的数
int c=0,s=0; //记录个数与和
for(int i=1;i*i<=n;i++){
if(n%i==0){
c+=2;
s=s+i+s/i; // 同时记录 i 和 s / i 两个因数
}
}
2. 拆解为数个质数的次方 的 积形式
若n= P1^n1 * P2^n2 * P3^n3 (Px 均为质数)
则因数个数 c=(n1+1)*(n2+1)*(n3+1)
各因数和 (1+p1+p1^2+.....+p1^n1)*(1+p2+p2^2+.....+p2^n2)*(1+p3+p3^2+.....+p3^n3)
对于以上两种方法,若是n给的是10进制整数,
第一种时间复杂度为根号n
而第二种就光弄一个够用的质数组已经差不多这个数了
int a[200] = { 2,3 };
int i , j, p = 2; //p记录数组下标
for ( j = 5; j<= n; j += 2) // n为要求的“小于n的质数集合”中的n。
如果这里用“j*j<=n”,那么在这里要记录集合最大个数(因为n可能是大于根号n的质数,不记录会导致n继续除之后为计算的a中元素),然后后面分解质因数的时候,n除完之前可能的所有质数,剩下的就为最后的质数。
{
for (i = 0; a[i] * a[i] <= j; i++) {
if (j % a[i] == 0)break;
} //判断一个数是否为质数,只需要判断其是否会被比它小的质数整除即可。并且同时利用对称性,a[i]<根号j即可
if (a[i] * a[i] > j) { //说明之前一直没有break(一直没有整除)
a[p] = j; p++;
}
}
而且第二种还要挨个求质因数和对应的指数(还可以优化),还要幂运算(当然利用快速幂可以大大缩减时间)
long long fastPower(long long base, long long power) { //快速幂
long long result = 1;
while (power > 0) {
if (power & 1) {
result = result * base;
}
power >>= 1;
base = (base * base);
}
return result;
}
int n;
int s=1,k=1; //s,k分别记录因数和,因数个数
for(j=0;a[j]*a[j]<=n;j++){
if(n%a[j]==0){
int p=1; //p为a[j]的指数+1
while(n%a[j]==0){
n/=a[j];
p++;}
k*=p;
s*=(fastPower(a[j],p)-1)/(a[j]-1);}} //等差数列求和公式
if(n>1){ // 因为之前利用了a[j]*a[j]<=n减少时间复杂度,而最后的n可能是大于最后的a[j]的质数,也可能是1
k*=2;s*=n+1;
} //最后这里的k,s即为所求
所以一般来说,用第一种速度更快
附带相关题目:
1. 四因数
2. 好因子最大数目