最近在准备蓝桥杯经常会遇到质数问题,虽然说求量数是否互为质数这种问题已经考烂了,是基础不过的题型了,但是对于我这种概念经常搞不懂的人真的很为难。本文主要是对质数题型做一个总结。
判断x是否为质数
public static boolean isPrime(int num) {
if (num < 2) {
return false;
}
for (int i = 2; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
判断一个数是否为质数的方法是,从2开始遍历到这个数的平方根。简单解释一下: 当判断一个数n是否为质数时,我们只需要判断它是否能被小于等于它的平方根的数整除即可。因为如果n能被一个大于它的平方根的数整除,那么这个数一定能被一个小于等于它的平方根的数整除。
举个例子,假设我们要判断15是否为质数。它的平方根约为3.87,所以我们只需要判断它是否能被2、3、4、5整除即可。如果它能被这几个数中的任何一个整除,那么它就不是质数;如果它不能被这几个数中的任何一个整除,那么它就是质数。
因此,在判断一个数是否为质数时,我们只需要遍历小于等于它的平方根的数即可,这样可以减少遍历的次数,提高判断的效率。就不多说了,相信大家第一次接触C语言的时候,素数就是典型的例子了。 下面才是我们的重头戏。
判断区间质因子的个数
我们会遇到这么一个问题:给定正整数n,在小于等于n中,有几个与n互质的数? 朴树算法:我们会将遍历n遍,去判断i是否是n的素因子。在判断是否是素数的时候,有要进行m次遍历,显然这个时间复杂度为O(n^2)。 那么我们会引入一个欧拉函数,什么是欧拉函数?欧拉函数是干什么的?这名字听的好高端,不用怕,我们简单了解一下就欧克。
什么是欧拉函数
欧拉函数主要用于计算小于或等于一个正整数n的正整数中,与n互质的数的数目。 诶,这不就和我们的题目不谋而合了嘛。接下来用一张图简单的看一下欧拉函数的公式,
那么你可以尝试一下套用欧拉函数的公式计算一下当n = 8时,其区间内互质的个数是不是4啦。
那么欧拉公司如何转换成代码呢?
private static long eulerFunction(long a) {
int res = a;
for (int i = 2; i <= a/i; i++) {
if (a % i == 0) {
res = res / i * (i-1);
while (a % i ==0) {
a /= i;
}
}
}
if (a > 1) {
res = res / a * (a-1);
}
return res;
}
练一练
题目:0互质数的个数 - 蓝桥云课 (lanqiao.cn)
解题代码:
import java.util.Scanner;
/**
* 有多少个x 与 a^b 互为质数
* 结果取模998244353
*
* 输入 a b
* @author colir
*
*/
public class 互质数的个数 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long a = scanner.nextLong();
long b = scanner.nextLong();
scanner.close();
long res = eulerFunction(a);
res = (res*fastpow(a, b-1)) % 998244353;
System.out.println(res);
}
// 计算互质的个数—— 欧拉函数
private static long eulerFunction(long a) {
long res = a;
for (int i = 2; i <= a/i; i++) {
if (a % i == 0) {
res = res / i * (i-1);
while (a % i ==0) {
a /= i;
}
}
}
if (a > 1) {
res = res / a * (a-1);
}
return res;
}
// 快速幂算法
private static long fastpow(long a,long b) {
long res = 1;
while(b > 0) {
if ((b & 1) > 0) {
res = (res * a) % 998244353;
}
a = (a * a) % 998244353;
b >>= 1;
}
return res;
}
}
本题涉及到了快速幂算法,上一期我做过笔记了,就不多说了,大家可以看一下【快速幂算法】这篇文章