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

相关文章
相关标签/搜索