Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一道公约数的难题

一道公约数的难题

作者头像
ACM算法日常
发布于 2022-03-04 04:44:27
发布于 2022-03-04 04:44:27
25800
代码可运行
举报
文章被收录于专栏:ACM算法日常ACM算法日常
运行总次数:0
代码可运行

本次周赛最后一题主要考察对公约数的使用。

题意:给一个数组,任意两个数字相乘,乘积结果可以被k整除的个数。

例子:

输入:nums = [1,2,3,4,5], k = 2

输出:7

暴力思路

这个题目如果使用暴力解法会超时,暴力解法就是遍历任意两个数字,计算结果能否整除k。复杂度。

优化思路

假设,任意两个数字x、y,如果,那么y有什么特点呢?

显然,我们可以求出k和x的最大公约数6,标准库有gcd函数可以直接求出结果。,也就是说,y只要是4的整数倍就可以和x结合起来被k整除。

有一个特殊情况是,如果,,公约数是2,,此时2的整数倍包括6,如果y取值为6,那么,此时会出现重复计数,需要最后过滤掉。

基于这个特性,我们不难推出解题逻辑:

1 统计数组中所有数字的次数

2 统计所有数字的整数倍的次数s,比如2,那么2、4、6、8...的次数都要算进去

3 通过上面的公约数推算计算y的情况个数

4 过滤特殊情况

5 返回ans/2,因为x和y是对称的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    long long coutPairs(vector<int>& nums, int k) {
        // 取得最大数字m
        int m = *max_element(nums.begin(), nums.end());
        // 创建2个数组
        vector<long long> cnt(m + 1), s(m + 1);
        //统计数字x出现的次数
        for (int x : nums) cnt[x] += 1;

        // 计算数字i的倍数的数量,比如2,那么2、4、6、8...所有数字的数量
        for (int i = 1; i <= m; i += 1)
            for (int j = i; j <= m; j += i) {
                s[i] += cnt[j];
            }
        long long ans = 0;
        for (int i = 1; i <= m; i += 1) {
            // 计算k-24 i-18最大公约数是6,k剩余部分是4
            // k-4 i-6
            int x = k / gcd(k, i);
            if (x <= m) ans += cnt[i] * s[x];
        }
        // 注意上面gcd出来的x可能是i的约数,这样重复计数了i,这里需要将i去掉
        for (long long i = 1; i <= m; i += 1)
            if ((long long)i * i % k == 0) ans -= cnt[i];
        return ans / 2;
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
P1029 最大公约数和最小公倍数问题
题目描述 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1.P,Q是正整数 2.要求P,Q以x0为最大公约数,以y0为最小公倍数. 试求:满足条件的所有可能的两个正整数的个数. 输入输出格式 输入格式: 二个正整数x0,y0 输出格式: 一个数,表示求出满足条件的P,Q的个数 输入输出样例 输入样例#1: 3 60 输出样例#1: 4 说明 P,Q有4种 3 60 15 12 12 15 60 3 暴力暴力
attack
2018/04/13
8810
​最大公约数、同余原理详解
欧几里得算法,也被称为辗转相除法,用于计算两个整数的最大公约数,其核心公式为:gcd(a,b) = gcd(b,a mod b)。
用户1142828
2025/04/12
1750
精读《算法题 - 统计可以被 K 整除的下标对数目》
今天我们看一道 leetcode hard 难度题目:统计可以被 K 整除的下标对数目。
黄子毅
2023/09/01
2840
精读《算法题 - 统计可以被 K 整除的下标对数目》
惊呆了,LeetCode居然挂了……LeetCode周赛第281场解析
不知道大家参加了上周日的LeetCode周赛没有,发生了一件活久见的事,LeetCode官网居然挂了,不仅是中国区挂了,而是全站都挂了,国际服的竞赛也进不去了……过了好久才恢复。
TechFlow-承志
2022/09/22
6830
惊呆了,LeetCode居然挂了……LeetCode周赛第281场解析
LeetCode 1979. 找出数组的最大公约数
我的CSDN博客地址 https://michael.blog.csdn.net/
Michael阿明
2021/09/06
5910
每日算法刷题Day11-最大公约数、数组去重
输入两个整数 a 和 b,请你编写一个函数,int gcd(int a, int b), 计算并输出 a 和 b 的最大公约数。
timerring
2022/09/27
4430
每日算法刷题Day11-最大公约数、数组去重
第十五届蓝桥杯C++B组省赛
按照题目描述来说,会议有五十人,如果不加任何限制条件,这五十个人两两握手的次数是:
用户11305458
2024/10/14
2860
第十五届蓝桥杯C++B组省赛
LeetCode 第 342 场周赛
2651. 计算列车到站时间 题目大意: 给你一个正整数 arrivalTime 表示列车正点到站的时间(单位:小时),另给你一个正整数 delayedTime 表示列车延误的小时数。 返回列车实际到站的时间。 注意,该问题中的时间采用 24 小时制。 ---- 思想: 签到题 返回 (arrivalTime + delayedTime) % 24 ---- 代码: class Solution { public int findDelayedArrivalTime(int arrivalTime,
浪漫主义狗
2023/05/01
3560
LeetCode 914. 卡牌分组(最大公约数)
每组都有 X 张牌。 组内所有的牌上都写着相同的整数。 仅当你可选的 X >= 2 时返回 true。
Michael阿明
2020/07/13
4750
LeetCode 914. 卡牌分组(最大公约数)
C++17 中的 std::gcd:探索最大公约数的现代 C++ 实现
在数学和编程中,最大公约数(GCD,Greatest Common Divisor)是一个非常重要的概念。它表示两个或多个整数共有约数中最大的一个。在 C++17 中,标准库引入了 std::gcd 函数,这使得计算最大公约数变得更加简单和高效。本文将详细介绍 std::gcd 的使用方法、实现原理以及一些实际应用场景。
码事漫谈
2025/02/12
4240
C++17 中的 std::gcd:探索最大公约数的现代 C++ 实现
2022-09-07:给你一个由正整数组成的数组 nums 。 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。 例如,序列 [4,6,16
数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
福大大架构师每日一题
2022/09/07
7190
2022-09-07:给你一个由正整数组成的数组 nums 。 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。 例如,序列 [4,6,16
2025-05-25:最大公约数相等的子序列数量。用go语言,给定一个整数数组 nums,需要计算满足以下条件的非空子序列对 (
2025-05-25:最大公约数相等的子序列数量。用go语言,给定一个整数数组 nums,需要计算满足以下条件的非空子序列对 (seq1, seq2) 的数量:
福大大架构师每日一题
2025/05/25
560
2025-05-25:最大公约数相等的子序列数量。用go语言,给定一个整数数组 nums,需要计算满足以下条件的非空子序列对 (
最大公约数的算法
算法的原理:   对于辗转相除法:i和j的最大公约数,也就是i和j都能够除断它。换句话讲,就是i比j的n倍多的那个数k(i = j*n + k,即i % j = k)应该也是最大公约数的倍数。所以就能转换成求k和j的最大公约数。同理,对于更相减损术,同样的道理,i比j大的部分也是最大公约数的倍数。 代码: 1 /** 2 * 求最大公约数算法汇总 3 * 4 */ 5 public class GCD { 6 public static void main(String[] arg
SecondWorld
2018/03/14
1.3K0
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-681 最大公约数和最小公倍数问题
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-681 最大公约数和最小公倍数问题
红目香薰
2023/02/23
2570
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-681 最大公约数和最小公倍数问题
【codevs1012】最大公约数和最小公倍数
输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数
饶文津
2020/05/31
6900
LeetCode周赛302,这也太卷了,20分钟ak也只有300名……
第302场的LeetCode周赛,由千挂科技赞助。进入前100名的可以获得简历内推机会。
TechFlow-承志
2022/09/21
2870
LeetCode周赛302,这也太卷了,20分钟ak也只有300名……
LeetCode 1819. 序列中不同最大公约数的数目
例如,序列 [4,6,16] 的最大公约数是 2 。 数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
Michael阿明
2021/09/06
3830
用C语言解决最大公约数问题
首先我们要考虑,什么是最大公约数,在数学中的定义是:最小公倍数是指两个或多个整数共有倍数中最小的一个。为了求出两个数的最下公倍数,可以采用枚举试错法。
用户10922923
2024/01/23
2290
用C语言解决最大公约数问题
萌新小白必做题(1):找两数间的最大公约数与最小公倍数
如果a>b,则a和b与a-b和b的最大公约数相同,即Gcd (a, b) = Gcd (a-b, b) 性质2 如果b>a,则a和b与a和b-a的最大公约数相同,即Gcd (a, b) = Gcd (a, b-a) 性质3 如果a=b,则a和b的最大公约数与a值和b值相同,即Gcd (a, b) = a = b
对编程一片赤诚的小吴
2024/01/23
1740
【趣学C语言和数据结构100例】1-5
【趣学C语言和数据结构100例】 问题描述 1.输入两个正整数 m 和 n,求其最大公约数和最小公倍数 2.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数 3.求 Sn = a + aa + aaa + … + a…a 之值,其中 a 是一个数字,n 表示 a 的位数,n、a 由键盘输入。例如: 2 + 22 + 222 + 2222 + 22222(此时 n=5) 4.求 1! + 2! + 3! + 4! + … + 20! (扩展)输入一个 n,求 n 的双阶乘,例如输入 20,求 2! + 4! + … + 18! + 20! 5.求 2/1 + 3/2 + 5/3 + 8/5 + … 前 20 项 代码分析 1. 最大公约数和最小公倍数 最大公约数(GCD)的解法 辗转相除法(也称欧几里得算法):直接从 m 和 n 中较小的数开始递减,直到找到能同时整除 m 和 n 的最大数 最小公倍数(LCM)的解法 (1)普通解法:使用公式 LCM = (m * n) / 最大公约数 来计算。 (2)暴力解法:通过不断增加 y 的值,直到 y 能同时被 m 和 n 整除。效率较低。 2. 输入一行字符,统计个数 定义数组str存储输入的字符串,定义四个整型变量,用来计数。初始值都设为0。 使用fgets函数从标准输入(stdin)读取一行字符,存储到str数组中。 (fgets函数用法:fgets(str, 100, stdin)) for循环遍历 (1)使用函数:isalpha函数检查是否为英文字母,isspace函数检查是否为空格,isdigit函数检查是否为数字。 (2)使用==: str[i] = =’ '等。 3. 求 Sn = a + aa + aaa + … + a…a 之值,其中 a 是一个数字,n 表示 a 的位数,n、a 由键盘输入。例如: 2 + 22 + 222 + 2222 + 22222(此时 n=5) 找规律:输入n和a,定义pre_num和num用来表示当前aaa和 a + aa + aaa,for循环即可,循环次数为n,使用pre_num += a * pow(10, i);。 4. 求 1! + 2! + 3! + 4! + … + 20! 找规律:关于阶乘,考虑数值过大,使用long long定义变量,factorial和sum用来表示当前3! 和 1! + 2! + 3!。 //求阶乘使用 for (j = 1; j <= i; j++) { factorial *= j; } (扩展)输入一个 n,求 n 的双阶乘,例如输入 20,求 2! + 4! + … + 18! + 20! 突然想到可以扩展题求n 的双阶乘,思路同上。 5. 求 2/1 + 3/2 + 5/3 + 8/5 + … 前 20 项 找规律:可发现,后一个的分子为前一个的分子+分母,后一个的分子为前一个的分子,定义sum为和,for循环求,每次吧前一个的分子给temp保管,分别赋值。 代码实现 #include <stdio.h> #include <cstring> #include <ctype.h> #include <math.h> int main() { // 1.输人两个正整数 m 和 n,求其最大公约数和最小公倍数 int m, n, i, gcd, lcm, x, y; printf("请输入两个正整数 m 和 n:"); scanf("%d %d", &m, &n); if(m<n) {x=m;y=n;} //x为求gcd时的小数,y为求lcm的大数 else {x=n;y=m;} while (m % x != 0 || n % x != 0) { x--; } printf("最大公约数为:%d\n", x); //最小公倍数(LCM)的解法 printf("方法一:最小公倍数为:%d\n", x = m * n / x); while (y % m != 0 || y % n != 0) { y++; } printf("方法二:最小公倍数为:%d\n", y); // 2.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数 char str[100]; int letters = 0; int spaces = 0; int digits = 0; int others = 0; int i; printf("请输入一行字符:"); fgets(str, 100, stdin); //存
LucianaiB
2024/10/23
1060
【趣学C语言和数据结构100例】1-5
推荐阅读
相关推荐
P1029 最大公约数和最小公倍数问题
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验