传送门:http://acm.jlu.edu.cn/joj/showproblem.php?pid=1716
约数个数定理:设n的标准素数分解为 n = (a1 ^ p1) * (a2 ^ p2) * ...... * (am * pm),那么n的约数个数就是(p1 + 1) * (p2 + 1) * ...... * (p3 + 1)。
这道题先预处理出36200以内素数,之后枚举l,u之间的数,进行求约数个数就行了。
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 31630;
int isPrime[maxn], prime[maxn], a[10010];
int max, max_i, n, l, u, cnt;
int main()
{
//筛选素数
for (int i = 0; i < maxn; ++i)
isPrime[i] = 1;
isPrime[0] = isPrime[1] = 0;
for (int i = 4; i < maxn; i += 2)
isPrime[i] = 0;
for (int i = 3; i < 180; ++i)
for (int j = i * i; j < maxn; j += 2 * i)
isPrime[j] = 0;
cnt = 0;
for (int i = 2; i < maxn; ++i)
if (isPrime[i]) prime[cnt++] = i;
scanf("%d", &n);
while (n--)
{
int x, k, temp;
scanf("%d%d", &l, &u);
max = 0;
for (int i = l; i <= u; ++i)
{
memset(a, 0, sizeof(a));
x = int(sqrt(i));
k = 0;
temp = i;
for (int j = 0; prime[j] <= x; ++j)
{
if (i % prime[j] != 0) continue;
while (temp % prime[j] == 0)
{
a[k]++;
temp /= prime[j];
}
k++;
if (temp == 1) break;
}
if (temp > 1)
a[k++]++;
int num = 1;
for (int j = 0; j < k; ++j)
num *= a[j] + 1;
if (num > max)
{
max = num;
max_i = i;
}
}
printf("Between %d and %d, %d has a maximum of %d divisors.\n", l, u, max_i, max);
}
return 0;
}