Prime Sieve

板子

1. 暴力

public List<Integer> ps(int num){
        ArrayList<Integer> ans = new ArrayList<>();
        if(num<=1){
            return ans;
        }
        outer:for(int i=2;i<=num;i++){
            for(int j=2;j<i;j++){
                if(i%j==0){
                    continue outer;
                }
            }
            ans.add(i);
        }
        return ans;
    }

暴力筛的想法很简单,就是2到i-1每个数看一眼能不能整除,都不能就是素数。

2. 根号

public List<Integer> ps(int num) {
        ArrayList<Integer> ans = new ArrayList<>();
        if(num<=1){
            return ans;
        }
        outer:for(int i=2;i<=num;i++){
            int sqrt = (int) Math.sqrt(i);
            for(int j=2;j<=sqrt;j++){
                if(i%j==0){
                    continue outer;
                }
            }
            ans.add(i);
        }
        return ans;
    }

根号筛的想法稍微多一点,如果一个数能分解成n = p*q,那么p,q一定一个大于等于根号n,另一个小于等于根号n。因此检查到根号n就可以。

3. 埃氏筛

public List<Integer> ps(int num) {
        ArrayList<Integer> ans = new ArrayList<>();
        if(num<=1){
            return ans;
        }
        boolean[] isPrime = new boolean[num+1];
        Arrays.fill(isPrime,false);
        for(int i=2;i<=num;i++){
            // still not marked as a prime
            if(!isPrime[i]){
                ans.add(i);
                // mark k*i,k>=2,k∈N*
                for(int k=2;k*i<=num;k++){
                    isPrime[k*i]=true;
                }
            }
        }
        return ans;
    }

全名埃拉托色尼筛。当一个数确定是素数,那么它的1、2、3、4、5……倍一定都是合数,因此简历标记数组isPrime。每次循环检查标记,若为True那么置入结果列表。同时把他的倍数(直到边界)全部置为False。从数学角度可以证明,埃氏筛的复杂度是O(nloglogn)

4. 欧拉筛

public List<Integer> ps(int num) {
        ArrayList<Integer> ans = new ArrayList<>();
        if(num<=1){
            return ans;
        }
        boolean[] isPrime = new boolean[num+1];
        Arrays.fill(isPrime,false);
        for(int i=2;i<=num;i++){
            if(!isPrime[i]) {
                ans.add(i);
            }
            for (int j = 0; (j < ans.size()) && (ans.get(j) * i <= num); j++) {
                isPrime[ans.get(j) * i] = true;
            }
        }
        return ans;
    }

埃筛的缺点是会有重复标记。比如2,3都是素数。那么2会标记一次6,3也会标记一次6,造成冗余。

欧拉筛在此基础上进一步优化,一个合数必定由多个素数组合而成。那么每次我们用已有素数和当前数组合,标记isPrime,可以使得isPrime中的每个数访问且仅访问一次。时间复杂度O(n)。

1. LC 3326 使数组非递减的最少除法操作次数

VP周赛420 T3。

一开始我给了个写起来简单但是跑起来很慢的解。首先因为结果数组非递减,因此最后那个数就是最大的。因此我们直接倒着开,从倒数第二个数开始往前走。如果当前数比后面一个数大,那么从2开始尝试寻找其最小因数。找到最小因数相当于除以了最大因数(真)。这个范围其实是在[2,nums[i+1]]的,并不用找到根号,这是因为如果你找不到不比后一个数大的因子那么就可以返回-1了。

class Solution:
    def minOperations(self, nums: List[int]) -> int:
        cnt = 0

        for i in range(len(nums)-2,-1,-1):
            if nums[i]>nums[i+1]:
                for j in range(2,nums[i+1]+1):
                    if nums[i]%j==0:
                        nums[i] = j
                        cnt += 1
                        break
            if nums[i]>nums[i+1]:
                return -1

        return cnt

然后这个解法跑了个6100ms,压线过了。后来发现其实可以预处理里面for j那段for loop。我们想找某个数最小因子是谁。不就相当于在欧拉筛里面看是哪个因子把他标记掉的嘛。如果这个数本身是素数,那么令minPrime[x] = -1即可。随后在循环中查询minPrime[nums[i]],如果为-1,或者比nums[i+1]大,那么返回-1,否则计数。

这题如果改成除以一个因子(不一定最大),那就比较难了。

def Euler_Prime_Sieve(mx:int)->List[int]:
    minPrime = [-1 for _ in range(mx+1)]
    primes = []
    is_Prime = [True for _ in range(mx+1)]
    for i in range(2,mx+1):
        if is_Prime[i]:
            primes.append(i)
        for k in primes:
            if i*k > mx:
                break
            is_Prime[i*k] = False
            minPrime[i*k] = k
    return minPrime

mp = Euler_Prime_Sieve(int(1e6))
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        cnt = 0

        for i in range(len(nums)-2,-1,-1):
            if nums[i]>nums[i+1]:
                if mp[nums[i]] == -1 or mp[nums[i]]>nums[i+1]:
                    return -1
                nums[i] = mp[nums[i]]
                cnt += 1

        return cnt

时间复杂度:

  1. 预处理O(k),k为数组最大值
  2. 倒序遍历O(n),查询预处理过了O(1)

总体O(n+k)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/896670.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

并查集 --- Java通用模版

什么是并查集 并查集可以解决什么问题&#xff1a;判断两个节点是否在一个集合&#xff0c;也可以将两个节点添加到一个集合中。 并查集常用于处理大规模数据下的元素分组问题&#xff0c;特别是在数据量极大时&#xff0c;使用正常的数据结构可能会导致空间或时间复杂度过高…

2024年10月21日计算机网络,乌蒙第一部分

【互联网数据传输原理 &#xff5c;OSI七层网络参考模型】 https://www.bilibili.com/video/BV1EU4y1v7ju/?share_sourcecopy_web&vd_source476fcb3b552dae37b7e82015a682a972 mac地址相当于是名字&#xff0c;ip地址相当于是住址&#xff0c;端口相当于是发送的东西拿什…

推荐一款功能强大的数据备份工具:Iperius Backup Full

Iperius Backup是一款非常灵活而且功能强大的数据备份工具&#xff0c;程序可以非常好的保护您的文件和数据的安全。支持DAT备份、LTO备份、NAS备份、磁带备份、RDX驱动器、USB备份、并且支持zip压缩和军事级别的AES 256位数据加密技术! 主要特色 云备份 Iperius可以自动地发…

STM32F1+HAL库+FreeTOTS学习18——任务通知

STM32F1HAL库FreeTOTS学习18——任务通知 1. 任务通知1.1 任务通知的引入1.2 任务通知简介1.3 任务通知的优缺点 2. 任务相关API函数2.1 发送任务通知2.1.1 xTaskGenericNotify()2.1.2 xTaskNotifyGive()和xTaskNotifyGiveIndexed()2.1.2 xTaskNotify()和xTaskNotifyIndexed()2…

【LeetCode:910. 最小差值 II + 模拟 + 思维】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

低功耗4G模组的小秘密:RSA算法示例驾到,通通闪开...

在实际应用中&#xff0c;低功耗4G模组的RSA算法示例具有重要的价值&#xff0c;所以今天我们学习合宙低功耗4G模组Air780EP_LuatOS_rsa示例&#xff1a; 1.简介 RSA算法的安全性基于&#xff1a;将两个大质数相乘很容易&#xff0c;但是想要将其乘积分解成原始的质数因子却非…

微信小程序广告组件被驳回之后怎么重新提交广告组件?

有时候遇到广告组件被退回的问题 这时需要重新提交一次程序代码&#xff0c;然后提交审核然后发布新版本之后&#xff0c;找到广告管理&#xff0c;即可看到广告组件是在正在审核状态中

CANoe_数据回放功能功能介绍_时间段(区间)选择

CANoe的日志回放功能&#xff0c;可以选择时间段回放&#xff0c;这样可以在数据量很大的时候快速定位分析数据问题点 CANoe日志回放功能概述 CANoe的日志回放功能允许用户重现和分析已记录的CAN总线或其他网络总线数据。这些日志文件通常以CANoe自己的日志格式&#xff08;.b…

C#学习笔记(一)

C#学习笔记&#xff08;一&#xff09; 简介第一章 上位机开发环境之 VS 使用和.NET 平台基础一、安装软件二、创建项目三、第一个Hello world四、解决方案与项目五、Debug 和 Release 的区别六、代码的生产过程七、CLR的其它功能 简介 C# .NET工控上位机开发 在工控领域&…

【AI 大模型】智能时代的核心驱动力

1. 引言&#x1f4dc;1.1 AI大模型的崛起与影响力&#x1f31f;1.2 本文的研究目的与结构&#x1f9d0; 2. AI大模型的基础概念与技术原理&#x1f4da;2.1 定义与核心特征&#x1f3af;2.2 深度学习架构基础&#x1f9e0;2.3 大规模数据训练的重要性&#x1f4ca;2.4 模型优化…

15分钟学Go 实战项目一:命令行工具

实战项目一&#xff1a;命令行工具 1. 引言 命令行工具是开发者常用的工具之一&#xff0c;它可以帮助用户通过命令行界面对程序进行控制和交互。在这节中&#xff0c;我们将创建一个简单的命令行工具&#xff0c;以帮助你理解Go语言的基本语法和如何处理命令行输入。在这个过…

HarmonyOS NEXT 应用开发实战(六、组件导航Navigation使用详解)

在鸿蒙应用开发中&#xff0c;Navigation 组件是实现界面间导航的重要工具。本文将介绍如何使用 Navigation 组件实现页面跳转及参数传递&#xff0c;确保你能轻松构建具有良好用户体验的应用。 当前HarmonyOS支持两套路由机制&#xff08;Navigation和Router&#xff09;&…

Dongle Sentinal在Jenkins下访问不了的问题

背景&#xff1a; 工作站部署的jenkins的脚本无法正常打包&#xff0c;定位后发现是本地获取不了license&#xff0c;但是使用usb over network的远程license都能获取并正常打包 分析&#xff1a; 获取不了license的原因是本地无法识别dongle。根据提供信息&#xff0c;之前…

力扣76~80题

题76&#xff08;困难&#xff09;&#xff1a; 分析&#xff1a; 这道题其实不难&#xff0c;但是是我做最久的了&#xff0c;我居然去用res去接所有可能得值&#xff0c;然后再求长度导致空间暴力&#xff0c;我还以为是我queue的问题。。。 最后用暴力求解解的&#xff0c…

Apache Seata Raft模式配置中心

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Apache Seata Raft模式配置中心 title: Seata Raft模式配置中心 author: 蒋奕晨-清华大学&…

Vue是一套构建用户界面的渐进式框架,常用于构建单页面应用

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

HCIE-Datacom题库_11_IPsecVPN【17道题】

一、单选题 1.IPsecSA(SecurityAssociation&#xff0c;安全联盟)有两种生成方式&#xff0c;分别是手工方式和IKE自动协商方式&#xff0c;以下关于这两种方式的描述中&#xff0c;错误的是哪一项? 手工方式和IKE方式建立的SA都支持动态刷新 IKE方式建立的SA,其生存周期由…

传奇架设GEE引擎数据库服务器提示:拒绝未授权ip连接服务器的解决办法

今天一个新手GM遇到一个问题&#xff0c;他有一个GEE引擎的传奇版本&#xff0c;数据库服务器提示&#xff1a;拒绝未授权ip连接服务器&#xff1a;222.186.50.212、111.162.159.87 1.189.121.156、14.204.122.13、1.189.141.27等等&#xff0c;出于担心服务器是否有异常&#…

【VUE安装本地自定义capacitor插件以及打包成安卓APK过程】

capacitor插件创建使用过程 1. 初始化一个vue项目2.安装capacitor依赖3.自动化创建插件4. 实现功能后构建插件,插件目录下生成dist文件夹5. vue项目中安装插件6. vue项目中使用接口7. 构建vue项目8.构建为安卓项目9.打包APK1. 初始化一个vue项目 过程省略,本案例用的vue3+ty…

AI编译器与TVM

由于AI芯片的特殊性和高度定制化&#xff0c;为了兼容硬件的多样性&#xff0c;AI模型必须能被高效地映射到各种AI芯片上。AI编译器将深度学习框架描述的AI模型作为输入&#xff0c;将为各种AI芯片生成的优化代码作为输出。AI编译器的目标是通过编译优化的方法将深度学习框架产…