【LeetCode周赛】2022上半年题目精选集——数学

news2024/11/30 6:38:44

文章目录

  • 2183. 统计可以被 K 整除的下标对数目⭐⭐⭐⭐⭐
    • 思路——数论(一个数乘上另一个数x是k的倍数,x最小是多少?)
      • 代码1——统计每个数的因子
      • 代码2——统计k的因子
  • 2245. 转角路径的乘积中最多能有几个尾随零
    • 思路(因子2和5的个数 + 前缀和)⭐⭐⭐⭐⭐
    • 代码
  • 2281. 巫师的总力量和⭐⭐⭐⭐⭐
    • 思路——贡献法(单调栈求左右端点) + 前缀和的前缀和
    • 代码
  • 2310. 个位数字为 K 的整数之和
    • 解法——枚举集合的大小
      • 代码1——自己写的
      • 代码2——力扣官解

https://leetcode.cn/circle/discuss/G0n5iY/

2183. 统计可以被 K 整除的下标对数目⭐⭐⭐⭐⭐

2183. 统计可以被 K 整除的下标对数目
在这里插入图片描述
提示:

1 <= nums.length <= 10^5
1 <= nums[i], k <= 10^5

思路——数论(一个数乘上另一个数x是k的倍数,x最小是多少?)

对于一个固定的数字 nums[j] ,要想和 nums[i] 配对,那么 nums[i] 必须是某个数字 x 的倍数。
那么 x 最小是多少呢? (为了找到所有符合条件的 nums[i] ,我们需要找到最小的 x)

从数论的结论来看, x = k g c d ( n u m s [ j ] , k ) x = \frac{k}{gcd(nums[j], k)} x=gcd(nums[j],k)k,这里 k 就是题目中的 k。
为什么呢?可以从因子的角度去考虑,如果 nums[j] 和 k 有一些公因子,那么可以从 k 中除去这些公因子,这样 x 会变小,那么除去最大公因子是最优的

代码1——统计每个数的因子

我们可以不断枚举 nums[j],在这个过程中记录前面枚举过的 x 的倍数有多少个记为 cnt[x],那么枚举到 nums[j] 的时候就给答案加上多少。

class Solution {
    final static int mx = 100001;
    // 记录每个数字的所有因子
    static List<List<Integer>> divisors = new ArrayList(mx);
    static {
        for (int i = 0; i < mx; ++i) divisors.add(new ArrayList());
        for (int i = 1; i < mx; ++i) {
            for (int j = i; j < mx; j += i) {
                // j是i的倍数,所以把i放进j的因子列表里
                divisors.get(j).add(i);
            }
        }
    }

    public long countPairs(int[] nums, int k) {
        long ans = 0;
        Map<Integer, Integer> cnt = new HashMap();
        for (int num: nums) {
            ans += cnt.getOrDefault(k / gcd(num, k), 0);
            for (int d: divisors.get(num)) {
                cnt.merge(d, 1, Integer::sum);
            }
        }
        return ans;
    }

    public static int gcd(int a, int b) {
        return b == 0? a: gcd(b, a % b);
    }
}

代码2——统计k的因子

注意到 x 是 k 的因子,因此可以将代码 1 中统计 num 的因子改为 统计 num 是 k 的哪些因子的倍数,这可以通过 枚举 k 的所有因子 来判断。

class Solution {

    public long countPairs(int[] nums, int k) {
        // 统计k的因子
        List<Integer> divisors = new ArrayList();
        for (int d = 1; d * d <= k; ++d) {
            if (k % d == 0) {
                divisors.add(d);
                if (d * d < k) divisors.add(k / d);
            }
        }

        long ans = 0;
        Map<Integer, Integer> cnt = new HashMap();
        for (int num: nums) {
            ans += cnt.getOrDefault(k / gcd(num, k), 0);
            for (int d: divisors) {
                if (num % d == 0) cnt.merge(d, 1, Integer::sum);
            }
        }
        return ans;
    }

    public static int gcd(int a, int b) {
        return b == 0? a: gcd(b, a % b);
    }
}

2245. 转角路径的乘积中最多能有几个尾随零

2245. 转角路径的乘积中最多能有几个尾随零

在这里插入图片描述
提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 10^5
1 <= m * n <= 10^5
1 <= grid[i][j] <= 1000

思路(因子2和5的个数 + 前缀和)⭐⭐⭐⭐⭐

在这里插入图片描述
计算出每个数字含有多少个 2 和 多少个 5,最后尾随 0 的个数就是 2 和 5 的数量的最小值。

代码

class Solution {
    static int[][] c25 = new int[1001][2];
    static {
        // 预处理,递推出每个数的因子2和因子5的个数
        for (int i = 2; i <= 1000; ++i) {
            if (i % 2 == 0) c25[i][0] = c25[i / 2][0] + 1;
            if (i % 5 == 0) c25[i][1] = c25[i / 5][1] + 1;
        }
    }

    public int maxTrailingZeros(int[][] grid) {
        int m = grid.length, n = grid[0].length, ans = 0;
        int[][][] s = new int[m][n + 1][2];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                // 每行的因子2或5的前缀和数量
                s[i][j + 1][0] = s[i][j][0] + c25[grid[i][j]][0];
                s[i][j + 1][1] = s[i][j][1] + c25[grid[i][j]][1];
            }
        }

        for (int j = 0; j < n; ++j) {       // 枚举每一列
            // 从上往下,枚举左拐还是右拐
            for (int i = 0, s2 = 0, s5 = 0; i < m; ++i) {
                s2 += c25[grid[i][j]][0];
                s5 += c25[grid[i][j]][1];
                int left = Math.min(s2 + s[i][j][0], s5 + s[i][j][1]);
                int right = Math.min(s2 + s[i][n][0] - s[i][j + 1][0], s5 + s[i][n][1] - s[i][j + 1][1]);
                ans = Math.max(ans, Math.max(left, right));
            }

            // 从下往上,枚举左拐还是右拐
            for (int i = m - 1, s2 = 0, s5 = 0; i >= 0; --i) {
                s2 += c25[grid[i][j]][0];
                s5 += c25[grid[i][j]][1];
                int left = Math.min(s2 + s[i][j][0], s5 + s[i][j][1]);
                int right = Math.min(s2 + s[i][n][0] - s[i][j + 1][0], s5 + s[i][n][1] - s[i][j + 1][1]);
                ans = Math.max(ans, Math.max(left, right));
            }
        }
        return ans;
    }
}

注意学习 递推出每个数的因子2和因子5的个数 的方法。
即:

static int[][] c25 = new int[1001][2];
static {
    // 预处理,递推出每个数的因子2和因子5的个数
    for (int i = 2; i <= 1000; ++i) {
        if (i % 2 == 0) c25[i][0] = c25[i / 2][0] + 1;
        if (i % 5 == 0) c25[i][1] = c25[i / 5][1] + 1;
    }
}

2281. 巫师的总力量和⭐⭐⭐⭐⭐

2281. 巫师的总力量和
在这里插入图片描述
提示:

1 <= strength.length <= 105
1 <= strength[i] <= 109

思路——贡献法(单调栈求左右端点) + 前缀和的前缀和

笔者认为本题的主要难点在于 前缀和的前缀和求法。

关于贡献法可见:【算法】贡献法相关题目练习

关于前缀和的前缀和的计算可见:https://leetcode.cn/problems/sum-of-total-strength-of-wizards/solutions/1510399/dan-diao-zhan-qian-zhui-he-de-qian-zhui-d9nki/ 或 下图计算过程。
请添加图片描述
注意这里说的所有子数组指的是所有包括元素 strength[i] 的子数组

代码

class Solution {
    public int totalStrength(int[] strength) {
        final int mod = (int)1e9 + 7;
        int n = strength.length;
        int[] s = new int[n + 1], ss = new int[n + 2];
        // 前缀和的前缀和
        for (int i = 0; i < n; ++i) {
            s[i + 1] = (s[i] + strength[i]) % mod;  
            ss[i + 2] = (ss[i + 1] + s[i + 1]) % mod;
        }
        int[] left = new int[n], right = new int[n];
        Arrays.fill(left, -1);
        Arrays.fill(right, n);
        Deque<Integer> stk = new ArrayDeque();
        for (int i = 0; i < n; ++i) {
            while (!stk.isEmpty() && strength[i] <= strength[stk.peek()]) right[stk.pop()] = i;
            if (!stk.isEmpty()) left[i] = stk.peek();
            stk.push(i);
        }

        long ans = 0;
        for (int i = 0; i < n; ++i) {
            int l = left[i] + 1, r = right[i] - 1;
            // 前缀和的前缀和推出的公式
            long tot = ((long)(i - l + 1) * (ss[r + 2] - ss[i + 1]) - (long)(r - i + 1) * (ss[i + 1] - ss[l])) % mod;
            ans = (ans + tot * strength[i]) % mod;
        }
        return (int)(ans + mod) % mod;
    }
}

2310. 个位数字为 K 的整数之和

2310. 个位数字为 K 的整数之和
在这里插入图片描述
提示:
0 <= num <= 3000
0 <= k <= 9

解法——枚举集合的大小

我们可以知道集合的大小不会超过 10,因为 11 个 个位是 k 的数字相乘,最后的个位数字还是 k ,没有影响。

代码1——自己写的

class Solution {
    public int minimumNumbers(int num, int k) {
        if (num == 0) return 0;
        int n = num % 10, ans = 1;
        while (ans < 11 && (ans * k % 10 != n)) ++ans;
        return ans <= 10 && ans * k <= num? ans: -1;
    }
}

自己写的代码丑陋了一下,因为循环写的不好所以需要对结果加一些额外的判断。

代码2——力扣官解

class Solution {
    public int minimumNumbers(int num, int k) {
        if (num == 0) return 0;
        for (int i = 1; i <= 10; ++i) {
            if (k * i <= num && (num - k * i) % 10 == 0) return i;
        }
        return -1;
    }
}

官解的答案优雅很多,依次判断 1 ~ 10 是否满足答案,满足就返回,不满足就最后返回 -1。

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

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

相关文章

探索全球市场:初创品牌海外营销策略解析

​随着全球化进程的不断推进&#xff0c;越来越多的初创品牌意识到海外市场的巨大潜力&#xff0c;并希望能够将自己的品牌推广到更广阔的国际舞台上。然而&#xff0c;对于初创品牌来说&#xff0c;进军海外市场并开展品牌营销是一项具有挑战性的任务。本文Nox聚星将介绍一些初…

百变探影器 - 是一款很多人都在用的剪辑软件

有没有一款剪辑软件&#xff0c;它不仅颜值高&#xff0c;不用花时间学习就会剪&#xff0c;还自带丰富转场、片头片尾、字幕模板呢&#xff1f;那不得不说的就是一款超级能打的国产剪辑软件—百变探影器软件。 Pr这些比较专业的剪辑软件&#xff0c;基本都需要拥有一定的剪辑…

【实验八】多线程

1、完成书上268页习题第7题和实验题第1、2题 &#xff08;1&#xff09;第7题 import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*;public class RollWords extends JFrame{ static RollWords.MyThread thre…

西门子S7-200西门子200plc以太网配置向导

方案摘要&#xff1a; 西门子 S7200 系列 PLC通过MatrikonOPC实现以太网连接&#xff0c;捷米特ETH-S7200-JM01以太网模块为 PLC200转换出以太网通讯接口。 功能简介 MatrikonOPC是世界上最大的OPC开发商和供应商&#xff0c;我们的产品涵盖了OPC服务器、客户端、应用程序、O…

为D1定义一个f()函数,重做练习1-3,并解释其结果

运行代码&#xff1a; //为D1定义一个f()函数&#xff0c;重做练习1-3,并解释其结果 #include"std_lib_facilities.h" //---------------------------------------------------------------------- //定义B1类。 class B1 { public:virtual void vf() { cout<<…

第四章 数学知识(二)——欧拉函数,快速幂,扩展欧与中国剩余定理

文章目录 欧拉函数线性筛求欧拉函数欧拉定理 快速幂逆元 扩展欧几里得中国剩余定理扩展中国剩余定理 欧拉函数练习题873. 欧拉函数874. 筛法求欧拉函数 快速幂练习题875. 快速幂876. 快速幂求逆元 扩展欧练习题877. 扩展欧几里得算法878. 线性同余方程 中国剩余定理练习题204. …

Linux进程信号(一)

信号产生 1.信号基础知识2.初步认识信号3.signal函数4.技术应用角度的信号5.调用系统函数向进程发信号6.由软件条件产生的信号7.硬件异常产生信号8.core &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f…

从CoCo到喜茶,新茶饮品牌领悟出海的“九阴真经”了吗?

炎炎夏日里&#xff0c;一杯冰凉的奶茶和果茶受到了更多追捧。但是&#xff0c;中国新茶饮品牌却站在了一个十字路口。 随着新茶饮迈入“万店时代”&#xff0c;国内市场已经出现了明显的内卷现象&#xff0c;头部品牌之间的竞争日趋激烈&#xff0c;中小品牌的生存空间被挤压…

OpenGL的学习记录(一)(一些基本概念)

1.OpenGL是什么&#xff1f; OpenGL是一组各个GPU厂家一起遵循的约定。 2.GLFW&#xff0c;GLAD分别是什么&#xff1f; GLFW解决系统层面的不同&#xff0c;是我们与系统之间的隔离&#xff0c;如&#xff08;创建窗口&#xff0c;定义上下文&#xff0c;处理用户输入&#x…

数据结构--树和森林的遍历

数据结构–树和森林的遍历 树的先根遍历 void PreOrder(TreeNode* R) {if (R ! NULL){visit(R);while (R还有下一个子树T)PreOrder(T);} }树和二叉树的转化后》 树的先根遍历序列与这棵树相应二叉树的先序序列相同。 \color{red}树的先根遍历序列与这棵树相应二叉树的先序序列相…

txt文本筛选—python操作

需求&#xff1a;若文档中某行最后一列内容为0&#xff0c;则删除该行&#xff0c;否则保留该行内容&#xff0c;并将筛选后的内容保存到新的文本文档中。 # 读取原始txt文件 with open(depth_values.txt, r) as file:lines file.readlines()# 过滤掉第三列内容为0的行 filter…

WIFISKY-7层流控路由器 后台任意命令执行漏洞复现

这个漏洞相当于是两个漏洞的结合&#xff0c;首先是弱口令漏洞 admin/admin 我们成功登录后台之后才能进行任意命令执行漏洞的操作&#xff0c;我们登录之后找到系统维护-系统控制台 然后我们使用命令拼接的操作来实现任意命令执行的操作 ifconfig & cat /etc/passwd

自定义seg_decoder组件并创建Nios系统(二)

3.搭建Nios Ⅱ系统 3.1添加组件 系统会自动添加一个clk的clock source组件作为时钟组件&#xff0c;可直接使用该组件作为系统时钟 添加Nios Ⅱ处理器&#xff0c;将Nios Processor组件设置框中Nios Core选择Nios Ⅱ/f&#xff08;报错先不管&#xff09; 添加On-chip Memory…

揭秘未来:AI、自然资源与时空大数据的完美结合!JNPF快速开发平台引领无限潜能!

前言 在当今数智时代&#xff0c;人工智能&#xff08;AI&#xff09;的应用正以前所未有的方式改变着各个领域的发展路径。尤其在融合自然资源、时空大数据的领域&#xff0c;AI呈现出了崭新的形式&#xff0c;展现着巨大的潜力与前景。 技术的发展离不开数据的支持 随着人工…

【STM32MP135】移除stm32mp135d-atk-u-boot.dtsi设备树config节点,否则会进入fastboot下载模式

文件路径&#xff1a;u-boot-stm32mp-v2021.10-stm32mp1-r1/arch/arm/dts/stm32mp135d-atk-u-boot.dtsi

TVS二极管原理

在管子两端的电压大于一定值时&#xff0c;TVS管被反向击穿&#xff0c;瞬间形成一个导通回路&#xff0c;将管子两端的大电流导出&#xff0c;并且将管子两段的电压钳制在一个固定电压&#xff0c;进而保护和它并联的电路。 挑选TVS管先看VRWM&#xff0c;尽量与最大工作电压接…

洛谷:P5018 对称二叉树 ← NOIP2018 普及组T4

【题目来源】https://www.luogu.com.cn/problem/P5018https://www.acwing.com/problem/content/478/【题目描述】一棵有点权的有根树如果满足以下条件&#xff0c;则被轩轩称为对称二叉树&#xff1a; 1.二叉树&#xff1b; 2.将这棵树所有节点的左右子树交换&#xff0c;新树和…

关于Python的Numpy库reshape()函数的用法

1.介绍 更改数组的形状&#xff0c;不改变原数组 2.语法 a np.reshape(mat, newshape, order ‘C’) a : newshape形状的新数组 mat : 原数组 newshape&#xff1a;(1, 2)/ 1, 2 都可以改为1行2列的数组 order&#xff1a;读取原数组的规则&#xff0c;默认为C&#xff08;…

Go语言精进之路读书笔记—第三章 声明、类型、语句与控制结构(五)map

map 是啥&#xff1f; 无序的 key value 键值对。 创建变量有两种方式&#xff1a; 基本操作&#xff1a; 插入数据&#xff1a; 获取数据&#xff1a; 查找和数据读取&#xff1a; comma ok 查找法, 被称为最佳实践。 获取value 删除数据 遍历数据 想要有序的需要这样做&a…

CSS 沿着同一个方向旋转

主要解决旋转360后倒转的问题&#xff0c;沿着一个方向旋转&#xff0c;而不是倒回去重新开始。 效果 源码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>同方向旋转</title><script src"https://dp.rc1…