JOJ1716:Divisors

来源:互联网 发布:win10系统网络连不起网 编辑:程序博客网 时间:2024/06/14 10:15

传送门: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;}