题意:
三角形数数列是通过逐个加上自然数来生成的。例如,第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个约数的三角形数是多少?
思路:
任何一个数都可以写成一个或多个素数的乘积,我们设为n = p1^n1 * p2 ^ n2 *…
因此,一个数的因子个数,等同于(n1 + 1) * (n2 + 1) *…
为什么呢?我们可以想一下,对于素因子p1,我们有n1 + 1种选择,分别是:不选,选一个,选两个…直到选n1个,同理p2有n2+1种选择,所以种类数就是(n1 + 1) * (n2 + 1) *…
因此,我们只需要计算一个数有多少种素因子,每种素因子的个数,就可以通过算式直接求得一个数的因子数,求法有两种:
——一种是预处理全部素数,然后每次遍历整除直到该数为1,时间复杂度是O(n),其中n为满足条件的数
——另一种方式是创建记忆化数组数组,存储每个数的最小素因子。再利用:如果a,b互质,那么num(a ✖️ b) = num (a) ✖️ num(b) ,又因为三角形数都是n / 2 ✖️ (n - 1)或n / 2 ✖️ (n + 1)(n >= 2且n为偶数),所以我们只预处理sqrt(n)项即可(注:num(a)代表数字a的因子数),时间复杂度为O(sqrt(n))
代码:
#include
#include
#include
#define ll int64_t
#define d int32_t
#define f double
#define r return
#define mem(a) memset(a, 0, sizeof(a));
#define N 40000
d book[N + 5]; //存储每个数的最小素因子
d prime[N + 5]; //存储2~40000全部素数
d number[N + 5]; //存储前40000数的因子数
//利用线性筛框架初始化
void init() {
mem(book);
mem(prime);
for (d i = 2; i <= N; i++) {
if (!book[i]) {
prime[++prime[0]] = i;
book[i] = i;
}
for (d j = 1; j <= prime[0] && prime[j] * i <= N; j++) {
book[prime[j] * i] = prime[j];
if (i % prime[j] == 0) break;
}
}
r;
}
//用于求S(n)
ll mul (ll n) {
r (n + 1) * n / 2;
}
//求n的因子数
d num(ll n) {
if (n == 1) r 1;
d res = 1;
d t = book[n];
while(n % t == 0) {
res++;
n /= t;
}
r res * num(n);
}
//利用当a,b互质,num(a * b) = num(a) * num(b)求a*b的因子数
void work () {
for (ll i = 1; i <= N; i++) {
number[i] = num(i);
}
for (ll i = 2; i <= N; i += 2) {
d p1 = number[i / 2] * number[i - 1];
d p2 = number[i / 2] * number[i + 1];
if (p1 > 500) {
printf("%" PRId64"\n", i / 2 * (i - 1));
r;
} else if(p2 > 500) {
printf("%" PRId64"\n", i / 2 * (i + 1));
r;
}
}
r;
}
d main () {
init();
work();
r 0;
}
答案是:76576500
转载请注明出处!!!
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢