hrbust 1328 - 相等的最小公倍數

題目連接: hrbust 1328php

這是一道數論的題目,求解方法仍是挺巧妙的,儘管夠基礎。ios

首先要知道的是多個數的最小公倍數究竟怎麼求,有一個公式爲lcm(a, b, c) = lcm(lcm(a,b),c),這個公式對n個數同樣也成立。 還有一種求法,是將這多個數均寫成素數因子的冪相乘的形式(惟一分解定理),而後對每一個素數因子,只取最大的指數,相乘就是最小公倍數了。算法

這裏用的是第二種想法,其實這種想法也是夠直觀,最接近直覺的。若是A(n)和A(n-1)是相等的,那麼說明n的素數因子冪相乘的形式中,沒有一個素數因子的冪是大於A(n-1)對應素數的冪的。 而若是n含有兩個及以上素數因子,好比(a^x)*(b^y),那x和y均不會超過A(n-1)對應素數的冪,由於a^x和b^y都是小於n的,A(n-1)中a和b的指數必定大於等於x和y。若是n能夠寫成a^x這種形式,那麼在A(n-1)的a因子的指數必定不會超過x,由於這麼大的指數是第一次出現的(特別地,當x爲1時,n爲素數)。spa

#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
vector<int> primes;
int not_prime[1010];
int main()
{
    for(int i = 2; i <= 1000; i++)
    {
        if(!not_prime[i])
        {
            primes.push_back(i);
            for(int j = 2; j*i <= 1000; j++) not_prime[i*j] = 1;
        }
    }
    int T;
    cin >> T;
    while(T--)
    {
        int n;
        scanf("%d", &n);
        if(n < 6) { printf("NO\n"); continue; }
        int yep = 1, cnt = 0;
        for(int i = 0; i < primes.size() && primes[i] * primes[i] <= n; i++)
        {
            if(n % primes[i]) continue;
            cnt++;
            int n_ = n;
            while(n_ % primes[i] == 0) n_ /= primes[i];
            if(n_ == 1) { yep = 0; break; }
        }
        if(yep && cnt) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

代碼裏用了素數篩查,n的規模是1000000,它的素數因子絕對會超過1000,這麼篩不會超時。code

其實算法裏面我最討厭的就是數論,由於我對這類題目不太敏感,每次出我都不知道該往哪想。可是即便不去專門搞數論,相似gcd、lcm、同餘、篩素數這樣的東西最好也要知道,我見過一些題目把數論融了進去,若是一點數論都不懂極可能會無從下手。ci

相關文章
相關標籤/搜索