【推荐】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、同余、筛素数这样的东西最好也要知道,我见过一些题目把数论融了进去,如果一点数论都不懂很可能会无从下手。
来源:oschina
链接:https://my.oschina.net/u/1780798/blog/638765