LeetCode --- 421周赛

news2024/12/23 2:02:41

题目列表

3334. 数组的最大因子得分

3335. 字符串转换后的长度 I

3336. 最大公约数相等的子序列数量

3337. 字符串转换后的长度 II

一、数组的最大因子得分

数据范围足够小,可以用暴力枚举移除的数字,得到答案,时间复杂度为O(n^2),代码如下

class Solution {
public:
    long long maxScore(vector<int>& nums) {
        int n = nums.size();
        auto get = [&](int i)->long long{
            // gcd(0, x) = x, lcm(1, x) = x
            long long x = 0; // 计算 gcd
            long long y = 1; // 计算 lcm
            for(int j = 0; j < n; j++){
                if(i == j) continue;
                x = gcd(x, nums[j]);
                y = lcm(y, nums[j]);
            }
            return x * y;
        };
        long long ans = get(-1); // 不去除任何数字
        for(int i = 0; i < n; i++){
            ans = max(ans, get(i));
        }
        return ans;
    }
};

有没有更快的做法?我们同样枚举被移除的数字,有没有方法能更加快速的算出剩余数字的 LCM 和 GCD?有的,只要我们提前算出左右两个部分的 LCM 和 GCD,就能直接计算得出剩余部分的LCM 和 GCD,即进行前后缀分解,时间复杂度为O(n),代码如下

注意:上面的时间复杂度默认 LCM 和 GCD 是O(1),但实际上 GCD/LCM 的时间复杂度为O(logn)

class Solution {
public:
    long long maxScore(vector<int>& nums) {
        int n = nums.size();
        vector<long long> suf_gcd(n + 1), suf_lcm(n + 1, 1);
        // gcd(0, x) = x, lcm(1, x) = x
        for(int i = n - 1; i >= 0; i--){
            suf_gcd[i] = gcd(suf_gcd[i + 1], nums[i]);
            suf_lcm[i] = lcm(suf_lcm[i + 1], nums[i]);
        }
        long long ans = suf_gcd[0] * suf_lcm[0]; // 不去除任何数
        long long pre_gcd = 0, pre_lcm = 1;
        for(int i = 0; i < n; i++){ // 同时计算 ans 和 前缀gcd/lcm
            ans = max(ans, gcd(pre_gcd, suf_gcd[i + 1]) * lcm(pre_lcm, suf_lcm[i+1]));
            pre_gcd = gcd(pre_gcd, nums[i]);
            pre_lcm = lcm(pre_lcm, nums[i]);
        }
        return ans;
    }
};

二、字符串转换后的长度 I

这题的数据范围比较小,我们可以模拟 t 次转换的过程。对于任意一个字母,它的转换规则是一样的,所以我们先统计出 26 个字母出现的次数,然后根据规则,进行转换即可,代码如下

class Solution {
    const int MOD = 1e9 + 7;
public:
    int lengthAfterTransformations(string s, int t) {
        vector<int> cnt(26);
        for(auto e : s) cnt[e - 'a']++;
        while(t--){
            vector<int>tmp(26);
            for(int i = 0; i < 26; i++)
                tmp[i] = cnt[(i-1+26)%26]; // 如'a'的出现次数变成'b'的出现次数
            // 'z' 不仅能变成 'a' , 还能变成 'b'
            tmp[1] =(tmp[1] + cnt[25]) % MOD;
            swap(tmp, cnt);
        }
        int ans = 0;
        for(int i = 0; i < 26; i++) ans = (ans + cnt[i]) % MOD;
        return ans;
    }
};

但是一旦 t 的范围过大,就会超时,有没什么更快的方法?由于每个字母的转移方式是固定的,所以只要给定一个字母和操作次数就能得到一个长度,问题是如何加速这个计算过程?

假设f[i][j]表示字母 i (用0-25表示) 经过 j 次操作的长度,我们有如下方程

代码如下

class Solution {
    const int MOD = 1e9 + 7;
    // 矩阵快速幂
    vector<vector<int>> POW(vector<vector<int>> a, int n){
        int m = a.size();
        vector<vector<int>> res(m, vector<int>(m));
        for(int i = 0; i < m; i++) res[i][i] = 1;
        while(n){
            if(n & 1) res = mul(res, a);
            a = mul(a, a);
            n >>= 1;
        }
        return res;
    }
    // 矩阵相乘
    vector<vector<int>> mul(const vector<vector<int>>& a, const vector<vector<int>>& b){
        int n = a.size(), m = b[0].size();
        vector<vector<int>> c(n, vector<int>(m));
        for(int i = 0; i < n; i++){
            for(int k = 0; k < n; k++){
                if(a[i][k] == 0) continue;
                for(int j = 0; j < m; j++){
                    c[i][j] = (c[i][j] + 1LL * a[i][k] * b[k][j]) % MOD;
                }
            }
        }
        return c;
    }
public:
    int lengthAfterTransformations(string s, int t) {
        int n = s.size();
        vector<vector<int>> mtx(26, vector<int>(26));
        for(int i = 0; i < 26; i++){
            mtx[i][(i+1)%26] = 1;
        }
        mtx[25][1] = 1;
        auto f = POW(mtx, t); // 矩阵的t次幂
        vector<int> cnt(26);
        for(auto e : s) cnt[e - 'a']++;
        long long ans = 0;
        for(int i = 0; i < 26; i++){
            ans += reduce(f[i].begin(), f[i].end(), 0LL) * cnt[i];
        }
        return ans % MOD;
    }
};

三、最大公约数相等的子序列数量

对于每一个数,都有三种可能,要么在seq1,要么在seq2,要么不选,一旦我们选择完一个数,对于剩下的数,我们依旧可以用相同的方法进行处理,大问题被划分为一个个小问题,进行解决。

设dfs(i,j,k)表示当seq1的gcd=j,seq2的gcd=k时,从前 i 个数中进行选择能得到的合法方案数

对于 nums[i]

  • 1、不选,方案数为 dfs(i-1,j,k)
  • 2、选入seq1,方案数为 dfs(i-1,gcd(j,nums[i]),k)
  • 3、选入seq2,方案数为 dfs(i-1,j,gcd(k,nums[i])) 

故状态转换方程为

dfs(i,j,k) = dfs(i-1,j,k) + dfs(i-1,gcd(j,nums[i]),k) + dfs(i-1,j,gcd(k,nums[i])) 

边界条件:当 i < 0 时,返回 j == k,表示将所有的数都进行分配后,如果seq1的gcd = seq2的gcd,则为一种合法方案数

代码如下

class Solution {
    const int MOD = 1e9 + 7;
public:
    int subsequencePairCount(vector<int>& nums) {
        int n = nums.size();
        int memo[n][201][201];
        memset(memo, -1, sizeof(memo));
        function<int(int,int,int)> dfs = [&](int i, int j, int k)->int{
            if(i < 0) return j == k;
            if(memo[i][j][k] != -1) return memo[i][j][k];
            int res = dfs(i - 1, j, k); // 不选
            res = (res + dfs(i - 1, gcd(j, nums[i]), k)) % MOD;
            res = (res + dfs(i - 1, j, gcd(k, nums[i]))) % MOD;
            return memo[i][j][k] = res;
        };
        // 注意我们的dfs会包含一种seq1和seq2都为空的方案,需要被减去
        // 由于取模操作 dfs(n - 1, 0, 0) - 1 可能为负数,所以要 + MOD) % MOD
        return (dfs(n - 1, 0, 0) - 1 + MOD) % MOD;
    }
};

四、字符串转换后的长度 II

这题的思路同第二题,只是计算的矩阵不同,具体代码如下

class Solution {
    const int MOD = 1e9 + 7;
    // 矩阵快速幂
    vector<vector<int>> POW(vector<vector<int>> a, int n){
        int m = a.size();
        vector<vector<int>> res(m, vector<int>(m));
        for(int i = 0; i < m; i++) res[i][i] = 1;
        while(n){
            if(n & 1) res = mul(res, a);
            a = mul(a, a);
            n >>= 1;
        }
        return res;
    }
    // 矩阵相乘
    vector<vector<int>> mul(const vector<vector<int>>& a, const vector<vector<int>>& b){
        int n = a.size(), m = b[0].size();
        vector<vector<int>> c(n, vector<int>(m));
        for(int i = 0; i < n; i++){
            for(int k = 0; k < n; k++){
                if(a[i][k] == 0) continue;
                for(int j = 0; j < m; j++){
                    c[i][j] = (c[i][j] + 1LL * a[i][k] * b[k][j]) % MOD;
                }
            }
        }
        return c;
    }
public:
    int lengthAfterTransformations(string s, int t, vector<int>& nums) {
        int n = s.size();
        vector<vector<int>> mtx(26, vector<int>(26));
        for(int i = 0; i < 26; i++){
            for(int j = i + 1; j <= i + nums[i]; j++){
                mtx[i][j%26] = 1;
            }
        }
        auto f = POW(mtx, t);
        vector<int> cnt(26);
        for(auto e : s) cnt[e - 'a']++;
        long long ans = 0;
        for(int i = 0; i < 26; i++){
            ans += reduce(f[i].begin(), f[i].end(), 0LL) * cnt[i];
        }
        return ans % MOD;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Java核心技术 卷I》第4章 对象与类

第4章 对象与类 面向对象程序设计(Object-Oriented Programming&#xff0c;OOP)。 实现一个简单的Web浏览器可能2000个过程&#xff0c;采用面向对象设计风格大约100个类&#xff0c;每个类平均包含20个方法。 类 类(class)是构造对象的模板或蓝图&#xff0c;我们可以将类…

【JavaScript】axios 二次封装拦截器(接口、实例、全局)

学习 coderwhy 老师结合 ts 二次封装 axios 目录结构 config config\index.ts // export const BASE_URL "http://codercba.com:9002"; export const TIME_OUT 10000;// 1. 根据环境变量区分接口地址 // let BASE_URL: string; // if (process.env.NODE_ENV &qu…

c++:vector模拟实现

一、vector成员变量 库里实现用的就是这三个成员变量&#xff0c;咱们实现跟库里一样&#xff0c; namespace myvector {template<class T>class vector{public://vecttor的迭代器是原生指针typedef T* iterator;typedef const T* const_iterator; private:iterator _sta…

数字后端零基础入门系列 | Innovus零基础LAB学习Day8

###LAB15 Detail Routing for Signal Integrity, Timing, Power and Design for Yield 这个章节虽然标题有点长&#xff0c;但不要被它吓到&#xff0c;其实这个章节就是Innovus工具的绕线Routing。只不过这个阶段做Route不是仅仅是把所有的逻辑连接&#xff0c;用实际的金属层…

发现研究的组织是自己所在组织,有点慌

donnyhuang 2019-5-29 23:34 我们做业务建模研究的组织可以是自己所在的组织吗&#xff1f;例如&#xff0c;如果我想做一个组件来来提高研发效能&#xff0c;那我研究的组织是我们部门的研发线可以吗&#xff1f; 因为最近做一个设备管理的建模&#xff0c;发现研究的组织是自…

将数学学生搞糊涂的糊涂话:面积(路程)是一种对应规则(关系)

黄小宁 将一种关系与构成此关系的成员、要素混为一谈是非常低级的常识性错误。问题是学生们做梦都不敢怀疑课本会有这样的错误。有战士与班长之间构成一种上下级关系&#xff0c;战士必须服从上级的指挥。将构成此关系中的班长说成是关系本身显然是概念性错误。同样&#xff0c…

(九)JavaWeb后端开发3——Servlet

目录 1.Servlet由来 2.Servlet快速入门 3.Servlet执行原理 4.Servlet生命周期 1.Servlet由来 在JaveEE API文档中对Servlet的描述是&#xff1a;可以运行在服务器端的微小程序&#xff0c;但是实际上&#xff0c;Servlet就是一个接口&#xff0c;定义了Java类被浏览器访问…

【51单片机】矩阵键盘

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 矩阵键盘 矩阵键盘 矩阵键盘位于开发板的右下角 在键盘中按键数量较多时&#xff0c;为了减少I/O口的占用&#xff0c;通常将按键…

特朗普概念股分析:DJT和Phunware股价大涨:买还是卖?

猛兽财经核心观点&#xff1a; &#xff08;1&#xff09;特朗普媒体科技集团的股价已经从9月份的低点上涨了280%。 &#xff08;2&#xff09;随着特朗普赢得大选的概率上升&#xff0c;Phunware的股价也在大幅上涨 &#xff08;3&#xff09;这些股票在大选后逆转的可能性越来…

Python | Leetcode Python题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; class Solution:def findLUSlength(self, strs: List[str]) -> int:def is_subseq(s: str, t: str) -> bool:pt_s pt_t 0while pt_s < len(s) and pt_t < len(t):if s[pt_s] t[pt_t]:pt_s 1pt_t 1return pt_s len(s)ans …

FlinkCDC-MYSQL批量写入

一、运行环境 &#xff08;1&#xff09;Flink&#xff1a;1.17.2 &#xff08;2&#xff09;Scala&#xff1a;2.12.20 &#xff08;3&#xff09;Mysql&#xff1a;5.7.43 ##开启binlog 二、代码示例 思路&#xff1a;通过滚动窗口收集一批数据推给sink消费。binlog日志对…

群控系统服务端开发模式-应用开发-上传配置功能开发

下面直接进入上传配置功能开发&#xff0c;废话不多说。 一、创建表 1、语句 CREATE TABLE cluster_control.nc_param_upload (id int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 编号,upload_type tinyint(1) UNSIGNED NOT NULL COMMENT 上传类型 1&#xff1a;本站 2&a…

【大语言模型】ACL2024论文-03 MAGE: 现实环境下机器生成文本检测

【大语言模型】ACL2024论文-03 MAGE: 现实环境下机器生成文本检测 目录 文章目录 【大语言模型】ACL2024论文-03 MAGE: 现实环境下机器生成文本检测目录摘要研究背景问题与挑战如何解决核心创新点算法模型实验效果&#xff08;包含重要数据与结论&#xff09;主要参考工作后续优…

C++设计模式结构型模式———组合模式

文章目录 一、引言二、组合模式三、总结 一、引言 组合模式是一种结构型设计模式&#xff0c; 可以使用它将对象组合成树状结构&#xff0c; 并且能像使用独立对象一样使用它们。代码实现中涉及了递归调用。组合模式与传统上的“类与类之间的组合关系”没有关联&#xff0c;不…

【C/C++】qsort函数的学习与使用

零.导言 在之前的文章中&#xff0c;我介绍了冒泡排序&#xff0c;即按ASCII码值把元素从小到大排序&#xff08;文章链接我放在了第五部分&#xff0c;有兴趣的小伙伴可以求看看&#xff09;。而今天我将继续介绍qsort函数&#xff0c;这个函数可以起到和冒泡排序一样的作用&a…

前段(vue)

目录 跨域是什么&#xff1f; SprinBoot跨域的三种解决方法 JavaScript 有 8 种数据类型&#xff0c; 金额的用什么类型。 前段 区别 JQuery使用$.ajax()实现异步请求 Vue 父子组件间的三种通信方式 Vue2 和 Vue3 存在多方面的区别。 跨域是什么&#xff1f; 跨域是指…

【elkb】索引生命周期管理

索引生命周期管理 Index lifecycle management(索引生命周期管理)是elasticsearch提供的一种用于自动管理索引的生命周期的功能。允许使用者定义索引的各个阶段&#xff0c;从创建至删除。并允许使用者在每个阶段定义索引需要执行的特定动作。这些动作包含索引创建&#xff0c…

基于SSM志愿者招募系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;志愿组织管理&#xff0c;组织信息管理&#xff0c;组织申请管理&#xff0c;志愿活动管理活动报名管理 用户账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;…

msys2更换国内源(多个文件(不是3个文件的版本!))

msys2更换国内源 起因排查答案如下mirrorlist.mingw64mirrorlist.ucrt64mirrorlist.mingw32mirrorlist.mingwmirrorlist.clang64mirrorlist.clang32mirrorlist.msys 不想看经过的直接跳到答案 起因 查了很多个教程大部分都是【打开MSYS2软件内的\etc\pacman.d\ 中3个文件&…

Spring Boot框架下的信息学科平台系统架构设计

3系统分析 3.1可行性分析 通过对本基于保密信息学科平台系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于保密信息学科平台系统采用Spring Boot框架&a…