UVA-294 Divisors(線性篩+唯一分解定理)

Mathematicians love all sorts of odd properties of numbers. For instance, they consider 945 to be an interesting number, since it is the first odd number for which the sum of its divisors is larger than the number itself.

    To help them search for interesting numbers, you are to write a program that scans a range of numbers and determines the number that has the largest number of divisors in the range. Unfortunately, the size of the numbers, and the size of the range is such that a too simple-minded approach may take too much time to run. So make sure that your algorithm is clever enough to cope with the largest possible range in just a few seconds.

Input

     The first line of input specifies the number N of ranges, and each of the N following lines contains a range, consisting of a lower bound L and an upper bound U, where L and U are included in the range. L and U are chosen such that 1 ≤ L ≤ U ≤ 1000000000 and 0 ≤ U − L ≤ 10000.

Output

       For each range, find the number P which has the largest number of divisors (if several numbers tie for first place, select the lowest), and the number of positive divisors D of P (where P is included as a divisor). Print the text ‘Between L and H, P has a maximum of D divisors.’, where L, H, P, and D are the numbers as defined above.

Sample Input

3

1 10

1000 1000

999999900 1000000000

Sample Outpu

t Between 1 and 10, 6 has a maximum of 4 divisors.

Between 1000 and 1000, 1000 has a maximum of 16 divisors.

Between 999999900 and 1000000000, 999999924 has a maximum of 192 divisors.

題意是兩個數n,m,要你求[n,m]之間因數最多的數和這個數的因數個數

解題思路:

        對於每個大於一的數,若本身不是素數,則一定可以被分解成若干個素數的乘積形式。

        比如12的唯一表達式爲12 = 2 ^ 2 * 3 ^ 1, 24的唯一表達式爲24 = 2 ^ 3 + 3 ^ 1

        首先,我們先通過線性篩得到1000000000以內的全部素數。然後對於當前的n進行循環判斷是否爲下標爲i的素數的倍數,是則n/=primeNum[i],計數器tmp++,否則循環結束,res *= tmp,然後開始判斷下一個素數

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int maxN = 36000;

int primeNum[maxN], cou = 0;
bool isUsed[maxN];

int Fun(int n) {
    int res = 1, tmp;
    for(int i = 0;i < cou && n != 1;i++) {
        tmp = 1;
        if(n % primeNum[i] == 0) {
            while(n % primeNum[i] == 0) {
                tmp++;
                n /= primeNum[i];
            }
        }
        res *= tmp;
    }
    return res;
}

int main() {
    memset(isUsed,0,sizeof(isUsed));
    for(int i = 2;i <= maxN;i++) {
        if(!isUsed[i]) {
            primeNum[cou++] = i;
        }
        for(int j = 0;j < cou && i * primeNum[j] <= maxN;j++) {
            isUsed[i * primeNum[j]] = true;
            if(i % primeNum[j] == 0){
                break;
            }
        }
    }
    int t, n, m, res, num;
    scanf("%d",&t);
    while(t--) {
        res = 0;
        num = 0;
        scanf("%d%d",&n,&m);
        for(int i = n;i <= m;i++) {
            if(Fun(i) > res) {
                res = Fun(i);
                num = i;
            }
        }
        printf("Between %d and %d, %d has a maximum of %d divisors.\n", n, m, num, res);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章