一.约数个数定理
对于任一一个正整数N,根据质因数分解定理其都可拆分为若干素数相乘的形式,则该正整数N 的约数个数为各素因子幂次加一后再相乘。(证明:排列组合问题)
如:72 = 2^3 + 3^2, 则72的约数个数为(3 + 1)*(2 +1)= 12。
二.拓展应用
设f(n)表示n的约数个数。
若A,B互素,C = A*B,则f(C)= f(A)* f(B).
证明:A和B互素意味着二者最大公约数为1,由约数个数定理可知,二者的素因子无交集,因为C = A*B,所以f(C)= f(A)* f(B)。
再如对于三角形数,其通项公式为n*(n + 1) / 2, 可以看出n和n + 1是互素的,且一奇一偶,则:
f = f(n) * f((n + 1) / 2), n为奇数时
f = f(n / 2) * f(n + 1), n为偶数时
如,本题:
其代码实现就可以通过约数个数定理及其推广完成
#include <stdio.h>
#define max_n 100000
int prime[max_n + 5] = {0};
int f[max_n + 5] = {0};//f[i]表示i的约数个数
int cnt[max_n + 5] = {0};//cnt[i]表示i的最小素因子的幂次
void is_prime(){
for(int i = 2; i < max_n; i++){
if(!prime[i]) {
prime[++prime[0]] = i;
f[i] = 2; //素数因子个数为2
cnt[i] = 1; //素数的最小素因子幂次为1
}
for(int j = 1; j <= prime[0]; j++){
if(i * prime[j] >= max_n) break;
prime[i * prime[j]] = 1;
if(i % prime[j] == 0) {//i为合数
f[i * prime[j]] = f[i] / (cnt[i] + 1) * (cnt[i] + 2);
cnt[i * prime[j]] = cnt[i] + 1;
break;
}else {//i是素数
f[i * prime[j]] = f[i] * f[prime[j]];
cnt[i * prime[j]] = 1;
}
}
}
return ;
}
int main(){
is_prime();
int n = 1;
int max = 0;
while(1){
if(n % 2 == 0) max = f[n / 2] * f[n + 1];
else max = f[(n + 1) / 2] * f[n];
if(max > 500){
printf("%lld", n * (n + 1) / 2);
break;
}
n++;
}
return 0;
}