hrbust 1328

丶灬走出姿态 提交于 2020-01-08 13:19:02

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

题目链接: hrbust 1328

这是一道数论的题目,求解方法还是挺巧妙的,尽管够基础。

首先要知道的是多个数的最小公倍数究竟怎么求,有一个公式为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为素数)。

#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,这么筛不会超时。

其实算法里面我最讨厌的就是数论,因为我对这类题目不太敏感,每次出我都不知道该往哪想。但是即使不去专门搞数论,类似gcd、lcm、同余、筛素数这样的东西最好也要知道,我见过一些题目把数论融了进去,如果一点数论都不懂很可能会无从下手。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!