整数因子个数
题目描述
高度可约的三角形数
三角形数数列是通过逐个加上自然数来生成的。例如,第7个三角形数是 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28。三角形数数列的前十项分别是:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …
让我们列举出前七个三角形数的所有约数:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
我们可以看出,28是第一个拥有超过5个约数的三角形数。
第一个拥有超过500个约数的三角形数是多少?
解题思路
最普通的做法就是用暴力枚举的办法但是时间复杂度较大可以用线性筛进行变形来降低复杂度,下面解释为什么可以用线性筛来计算因子个数。首先可以知道任何正整数都可以分解成若干个素数相乘,那么数字因子个数如下图所示
例如72 = 2的3次方×3的2次方因此72的因子个数就是(3 + 1)×(2 + 1)= 12
另外我们要知道如果N和M互质(最大公约数是1)那么F(N* M)= F(N) * F(M)如果N和M不互质会在下面代码处解释
代码演示
#include <stdio.h>
#define max_n 100000
int prime[max_n + 5] = {0};
int f[max_n + 5] = {0}; //f数组记录约数个数
int cnt[max_n + 5] = {0};
//cnt主要是记录i中prime[j]的次数例如prime[j] = 2 ,i =4那么f[prime[j] * i] = (2 + 1)/( 2 + 1) * (2 + 2)
void init() {
for (int i = 2; i <= max_n; i++) {
if (!prime[i]) {
prime[++prime[0]] = i;
f[i] = 2; // 素数约数个数是两个
cnt[i] = 1;
}
for (int j = 1; j <= prime[0]; j++) {
if (prime[j] * i > max_n) break;
prime[prime[j] * i] = 1;
if (i % prime[j] == 0) {
f[prime[j] * i] = f[i] / (cnt[i] + 1) * (cnt[i] + 2); //不互素时
cnt[prime[j] * i] = cnt[i] + 1;
break;
} else {
f[prime[j] * i] = f[prime[j]] * f[i]; //prime[j] 和i互素时
cnt[prime[j] * i] = 1;
}
}
}
return ;
}
int main() {
init();
long long f_max = 0, n = 1;
while (1) {
if (n & 1) {
f_max = f[n] * f[(n + 1) >> 1];
} else {
f_max = f[n >> 1] * f[n + 1];
}
if (f_max > 500) break;
n += 1;
}
printf("%lld\n", n * (n + 1) / 2);
return 0;
}
整数的因子值和
代码演示
#include <stdio.h>
#include <math.h>
#define max_n 100000
int prime[max_n + 5] = {0};
int f[max_n + 5] = {0};
int cnt[max_n + 5] = {0};
int fac[max_n + 5] = {0};
void init() {
for (int i = 2; i <= max_n; i++) {
if (!prime[i]) {
prime[++prime[0]] = i;
f[i] = 2;
fac[i] = 1 + i;
cnt[i] = 1;
}
for (int j = 1; j <= prime[0]; j++) {
if (prime[j] * i > max_n) break;
prime[prime[j] * i] = 1;
if (i % prime[j] == 0) {
fac[prime[j] * i] = fac[i] / (pow (prime[j] , cnt[i] + 1) - 1) * (pow (prime[j], cnt[i]+ 2) - 1);
f[prime[j] * i] = f[i] / (cnt[i] + 1) * (cnt[i] + 2);
cnt[prime[j] * i] = cnt[i] + 1;
break;
} else {
fac[prime[j] * i] = fac[prime[j]] * fac[i];
f[prime[j] * i] = f[prime[j]] * f[i];
cnt[prime[j] * i] = 1;
}
}
}
return ;
}
int main() {
init();
return 0;
}