$n$ 以下の整数での,約数の個数の最大値を計算しておく.たとえば,$n = 10$ のときには,6 と 8 がおのおの 1,2,3,6 および 1,2,4,8 と,4個の約数を持ち,これが最大.$n=100$なら,たとえば72が12個の約数 1,2,3,4,6,8,9,12,18,24,36,72 を持つ.
結果
$n$ | 個数 |
---|---|
$10$ | 4 |
$10^2$ | 12 |
$10^3$ | 32 |
$10^4$ | 64 |
$10^5$ | 128 |
$10^6$ | 240 |
$10^7$ | 448 |
$10^8$ | 768 |
$10^9$ | 1344 |
$10^{10}$ | 2304 |
$10^{11}$ | 4032 |
$10^{12}$ | 6720 |
$10^{13}$ | 10752 |
$10^{14}$ | 17280 |
$10^{15}$ | 26880 |
$10^{16}$ | 41472 |
$10^{17}$ | 64512 |
たとえば $n \leq 10^5$ なら,$n$ の約数全体を二重ループで回しても 20,000回くらいで終わる,とかがわかる.
コード
#include <bits/stdc++.h>
#include <cassert>
using namespace std;
// Prime numbers up to 100.
// Note that their product is larger than 2^64.
vector<int> primes({2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97});
// Returns the maximum number of divisors of number s such that
// t * s <= n and all prime divisors of s are greater than or equal
// to primes[i]
int num_div(long long int n, long long int t, int i) {
int p = primes[i];
int ret = 1;
int r = 1;
long long int q = p; // q = p ^ r
while (t * q <= n) {
ret = max(ret, (r + 1) * num_div(n, t * q, i + 1));
q *= p;
r++;
}
return ret;
}
// Returns 10^n
long long int pow10(int n) {
long long int ret = 1;
while (n-- > 0) ret *= 10;
return ret;
}
int main(/* int argc, char *argv[] */) {
for (int k = 1; k <= 18; k++) {
cout << "10^" << k << " " << num_div(pow10(k), 1, 0) << endl;
}
return 0;
}
EDIT (2020/08/22): 単独でコンパイルできるようにコードを修正.