蓝桥杯 20541魔法科考试

小明正在参加魔法科的期末考试,考生需要根据给定的口诀组合出有效的魔法。其中,老师给定了 nn 个上半部分口诀 a1,a2,...,ana1​,a2​,...,an​ 和 mm 个下半部分口诀 b1,b2,...,bmb1​,b2​,...,bm​,均用整数表示。完整的口诀包含一个上半部分口诀和一个下半部分口诀,当选用两个口诀 aiai​ 和 bjbj​,将组合出完整口诀 S=ai+bjS=ai​+bj​。

当 SS 满足 S≤n+mS≤n+m 且 SS 为质数时,魔法是有效的。魔法的种类只和 SS 的大小有关。如果每个上半部分口诀和每个下半部分口诀在不同的组合中可以重复使用,小明想知道一共可能组合出多少种不同的有效魔法?

输入格式

输入共三行。

  • 第一行为两个正整数 n,mn,m。
  • 第二行为 nn 个由空格分开的正整数 a1,a2,...,ana1,a2,...,an。
  • 第三行为 mm 个由空格分开的正整数 b1,b2,...,bmb1,b2,...,bm。

输出格式

输出共 11 行,一个整数表示答案。

样例输入

复制代码
3 4
2 3 10
3 4 5 1

样例输出

复制代码
3

样例说明

可以组合出 3,5,73,5,7 这三个有效魔法。

java 复制代码
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();

        int[] n1 = new int[n];
        int[] m1 = new int[m];

        for (int i = 0; i < n; i++) {
            n1[i] = in.nextInt();
        }
        for (int i = 0; i < m; i++) {
            m1[i] = in.nextInt();
        }
        in.close();

        // 优化点 1: 使用筛法预处理素数,时间复杂度 O((n+m) log log (n+m))
        boolean[] isPrime = sieve(n + m);

        // 优化点 2: 将其中一个数组存入HashSet,用于O(1)时间复杂度的查找
        Set<Integer> setN = new HashSet<>();
        for (int num : n1) {
            setN.add(num);
        }

        Set<Integer> resultSet = new HashSet<>();

        // 遍历第二个数组
        for (int num : m1) {
            // 遍历所有可能的素数 p
            // p 的最小值为 2 (1+1),最大值为 n+m
            for (int p = 2; p <= n + m; p++) {
                if (isPrime[p]) { // 如果 p 是素数
                    int complement = p - num;
                    // 检查 complement 是否在第一个数组中存在
                    if (setN.contains(complement)) {
                        resultSet.add(p);
                    }
                }
            }
        }

        System.out.println(resultSet.size());
    }

    /**
     * 埃拉托斯特尼筛法,用于找出 0 到 max 之间的所有素数。
     * @param max 筛法的上限
     * @return 一个布尔数组,isPrime[i] 表示 i 是否为素数
     */
    private static boolean[] sieve(int max) {
        if (max < 2) {
            return new boolean[0]; // 没有素数
        }
        boolean[] isPrime = new boolean[max + 1];
        Arrays.fill(isPrime, true);
        isPrime[0] = isPrime[1] = false;

        // 只需遍历到 sqrt(max)
        for (int i = 2; i * i <= max; i++) {
            if (isPrime[i]) { // 如果 i 是素数,那么它的倍数都不是素数
                // 从 i*i 开始标记,因为更小的倍数已经被标记过了
                for (int j = i * i; j <= max; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        return isPrime;
    }
}
相关推荐
岁岁种桃花儿几秒前
kubenetes从入门到上天系列第二十六篇:Kubernetes的Istio服务网格实战
java·kubernetes·istio
JavaEdge.2 分钟前
openclaw 本地部署实战:含网关启动 + 本地模型接入完整步骤
java·openclaw
loserwang3 分钟前
Fluss#1386: 从日志恢复中的 OutOfOrder 来看 LEO、HW 与 Checkpoint 的区别
java·后端
毕设源码-邱学长4 分钟前
【开题答辩全过程】以 咖啡馆管理系统的设计与实现为例,包含答辩的问题和答案
java
NGC_66119 分钟前
JDK1.7 与 JDK1.8 ConcurrentHashMap:从分段锁到桶级锁的进化
java·开发语言
酉鬼女又兒10 分钟前
零基础快速入门前端DOM核心知识点详解与蓝桥杯Web赛道备考指南(可用于备赛蓝桥杯Web应用开发)
前端·职场和发展·蓝桥杯
大黄说说11 分钟前
PHP 数组 vs SPL 数据结构:队列与栈场景下的性能对决
开发语言·数据结构·php
leaves falling17 分钟前
C++类和对象(3)(初始化列表,类型转换,static成员,友元)
java·开发语言·c++
宵时待雨18 分钟前
C++笔记归纳15:封装map & set
开发语言·数据结构·c++·笔记·算法
色空大师20 分钟前
【网站开发-java】
java·linux·服务器·开发语言·网站·搭建网站