蓝桥杯简单数论
·
数论是研究整数性质的算法题型,在蓝桥杯占比 20%~30%,是最容易拿分、最依赖模板的板块。
核心高频方向:
-
最大公约数 / 最小公倍数
-
质数判断与质数筛(埃氏筛)
-
快速幂
-
因数与倍数
一、最大公约数
1、原理
不断用大数取余小数,把数字缩小。
辗转相除法: gcd(a,b) = gcd(b, a%b)
直到 b=0,a 就是最大公约数。
2、运用
// 辗转相除法求最大公约数
public static long gcd(long a, long b) {
// 当 b 不为 0 时,继续循环
while (b != 0) {
long temp = b; // 保存 b
b = a % b; // a, b 变成 b, a%b
a = temp; // a 更新为原来的 b
}
return a; // 最后 a 就是最大公约数
}
def gcd(a, b): while b != 0: a, b = b, a % b # 同步赋值,简化写法 return a
二、最小公倍数
1、原理
必须依赖最大公约数:
公式:LCM(a,b) = a × b // GCD(a,b)
注意:必须先除后乘,防止溢出
2、运用
public static long lcm(long a, long b) {
return a / gcd(a, b) * b; // 先除再乘,不溢出
}
def lcm(a, b): return a // gcd(a, b) * b
例题
推导结论:N = 最小公倍数 - a - b
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
long a=20250412l;
long b=20240413l;
long g=gcd(a,b);
long lcm=a*b/g;
System.out.println(lcm-a-b);
}
public static long gcd(long a,long b){
while(b!=0){
long temp=b;
b=a%b;
a=temp;
}
return a;
}
}
三、质数与埃氏筛
1、质数判断
普通判断法(适合小数据)
一个数从 2 试用到 √n,能整除就不是质数。
缺点:多次判断会超时。
public static boolean isPrime(long n) {
if (n < 2) return false; // <2 不是质数
// 只需循环到根号 n,优化效率
for (long i = 2; i * i <= n; i++) {
if (n % i == 0) { // 能被整除,说明是合数
return false;
}
}
return true;
}
def is_prime(n): if n < 2: return False i = 2 while i * i <= n: if n % i == 0: return False i += 1 return True
例题
import java.util.Scanner;
import java.util.*;
// 或者精确导入:import java.util.Set; import java.util.HashSet;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n=scan.nextInt();
int m=scan.nextInt();
int arrn []=new int[n];
int arrm []=new int[m];
for(int i=0;i<n;i++){
arrn[i]=scan.nextInt();
}
for(int i=0;i<m;i++){
arrm[i]=scan.nextInt();
}
Set<Long> set =new HashSet<>();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
long s=arrn[i]+arrm[j];
if(s<=(m+n)&&isPrime(s)){
set.add(s);
}
}
}
System.out.println(set.size());
scan.close();
}
public static boolean isPrime(long a){
if (a<2) return false;
for(long i=2;i*i<=a;i++){
if(a%i==0){
return false;
}
}
return true;
}
}
这样常规的去求解,会导致超时,无法完全通过,这时候就需要质数的埃氏筛法
什么是埃氏筛
埃氏筛(埃拉托斯特尼筛法)是一次性找出一段范围内所有质数的高效算法,专门解决 “多次判断质数导致超时” 的问题。
核心思想
先假设所有数都是质数,再把所有合数(非质数)“筛” 掉,最后剩下的就是质数。
步骤(以筛 2~200 为例)
-
建表:开一个布尔数组
isPrime,下标代表数字,先把2~200全部标记为true(假设都是质数)。 -
筛除:从 2开始遍历:
如果当前数
i是质数(isPrime[i] = true),就把i的所有倍数(从i*i开始)都标记为false(因为它们是合数)。 -
结果:数组里最后还是
true的下标,就是质数。
boolean [] isPrime=new boolean[n+m+1]; // 记录质数的布尔数组
for(int i=2;i<=n+m;i++) isPrime[i]=true; //先假设所有的数都是质数
for(int i=2;i*i<=n+m;i++){
if(isPrime[i]){
for(int j=i*i;j<=n+m;j+=i){
isPrime[j]=false;
}
}
}
// 为什么从 i*i 开始标记,而不是从 2*i 开始?
// 对于质数 i,小于 i*i 的倍数(比如 2i, 3i, ..., (i-1)i),其实已经被更小的质数筛掉了。
// 比如 i=5,2*5=10 已经被 i=2 筛过,3*5=15 被 i=3 筛过,4*5=20 被 i=2 筛过,所以直接从 5*5=25 开始标记就够了。
Set<Integer> set =new HashSet<>();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int s=arrn[i]+arrm[j];
if(s>=2&&s<=(m+n)&&isPrime[s]){
set.add(s);
}
}
}
System.out.println(set.size());
四、快速幂
1、核心原理
求 a 的 b 次方再取模。
暴力循环会超时,快速幂能秒算
把指数拆成二进制,时间复杂度 O (log n)
2、代码
public static long powMod(long a, long b, long mod) {
long res = 1; // 结果初始为 1
a = a % mod; // 先取模,防止 a 过大
while (b > 0) {
if ((b & 1) == 1) { // 二进制最后一位是 1
res = res * a % mod; // 结果乘上当前 a
}
a = a * a % mod; // a 平方
b = b >> 1; // 指数除以 2
}
return res;
}
def pow_mod(a, b, mod):
res = 1
a = a % mod
while b > 0:
if b % 2 == 1:
res = res * a % mod
a = a * a % mod
b = b // 2
return res
例题
五、因数个数统计
1、原理
因数成对出现:
12 = 1×12 = 2×6 =×4
3
所以只需要循环到 √n 就能统计完。
2、代码
int n = sc.nextInt();
int count = 0;
// 循环到根号 n 即可,因数成对出现
for (int i = 1; i * i <= n; i++) {
if (n % i == 0) {
if (i == n / i) {
count++; // 平方数,只算一次
} else {
count += 2; // 一对因数
}
}
}
System.out.println(count);
n = int(input())
count = 0
for i in range(1, int(n**0.5) + 1):
if n % i == 0:
if i == n // i:
count += 1
else:
count += 2
print(count)
更多推荐


所有评论(0)