294 - Divisors(唯一分解定律)

该题运用了唯一分解定律,详情请见lrj紫书P321,一个数的约数的个数就是将该数唯一分解之后,各质因子的系数+1之积 。虽然有一个快速算每一个数的约数个数的欧拉phi函数值,但是该题的数据范围非常大,数组存不下,而且区间差非常小,显然事先算出每一个数的约数个数不是一个明智的决定。 所以我们用的时候再算也不迟。  那么我们需要事先打出素数表,要多少素数呢? sqrt(10^9)就够了,因为如果一个素数比这个值还大,那么她的平方肯定超过了10^9,不在数据范围内,得到的系数一定是1,相当于没有乘。

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 55555;
int T,n,m,cnt = 0,vis[maxn+5],prime[maxn+5];
ll a,b;
void init() {
    int m = sqrt(maxn+0.5);
    for(int i=2;i<=m;i++) if(!vis[i])
        for(int j=i*i;j<=maxn;j+=i) vis[j] = 1;
    for(int i=2;i<=maxn;i++) if(!vis[i])
        prime[cnt++] = i;
}
ll C(int n,int cnt) {
    ll sum = 1;
    for(int i=0;i<cnt;i++) {
        int cur = 1;
        while(n % prime[i] == 0) {
            n /= prime[i];
            cur++;
        }
        sum *= cur;
    }
    return sum;
}
int main() {
    init();
    scanf("%d",&T);
    while(T--) {
        ll ans = 0, res = 1;
        scanf("%lld%lld",&a,&b);
        for(ll i = a; i <= b; ++i) {
            ll cur = C(i,cnt);
            if(cur > ans) {
                ans = cur;
                res = i;
            }
        }
        printf("Between %lld and %lld, %lld has a maximum of %lld divisors.\n",a,b,res,ans);
    }
    return 0;
}


你可能感兴趣的:(数论,uva,ACM-ICPC,唯一分解定律)