蓝桥杯2022年第十三届省赛真题-GCD

文章讲述了在给定正整数a和b的情况下,找到使gcd(a+k,b+k)最大的k值,利用更相减损术简化问题,提供C++代码示例。

题目 2682: 

蓝桥杯2022年第十三届省赛真题-GCD

时间限制: 3s 内存限制: 576MB 提交: 2999 解决: 800

题目描述

给定两个不同的正整数 a, b,求一个正整数 k 使得 gcd(a + k, b + k) 尽可能大,其中 gcd(a, b) 表示 a 和 b 的最大公约数,如果存在多个 k,请输出所有满足条件的 k 中最小的那个。 

输入格式

输入一行包含两个正整数 a, b,用一个空格分隔。 

输出格式

输出一行包含一个正整数 k。

样例输入

复制

5 7

样例输出

复制

1

提示

对于 20% 的评测用例,a < b ≤ 105 ;
对于 40% 的评测用例,a < b ≤ 109 ;
对于所有评测用例,1 ≤ a < b ≤ 1018 。

解题思路

        gcd性质中,根据更相减损术可以知道一个等式:gcd(a,b)=gcd(a,b-a)  当然这里的前提时a<=b;所以gcd(a+k,b+k)=gcd(a+k,b-a)  这里的a和b都是已知的。我们可以设c=b-a    即c是已知的  所以想要使得a+k与c的最大公因子尽可能地大。因为最大最大能到达c 。显然这个式子的最大gcd一定为 c ,我们只需要计算出a 最少需要增加多少可以成为 c 的倍数,这个增量即是答案k。

例如:

 a=5,b=7;求出c=7-5=2;d=a/c=5/2=1;如果a,c还差几个数成为倍数,需要再进行求余数a%c - d++;最后求出其相差多少个数d*c-a;

实现代码

#include<iostream>
using namespace std; 

int main()

{
    long long a,b,c,d;

    cin>>a>>b;

    if(a>b){
        long long t=a;
        a=b;
        b=t;
    }
    c=b-a;
    d=a/c;

    if(a%c) 
        d++;

    cout<<d*c-a<<endl;
    return 0;
} 

<think>好的,我需要分析用户的需求,他想预测2025蓝桥杯JAVA C组的可能考题,并希望得到样题和题解。首先,我需要回顾往真题,特别是JAVA C组的题目趋势,但用户提供的引用是关于C/C++ B组的,不过可能题型和考点有相似之处。根据引用中的例子,比如模拟题、图论算法(Floyd算法)、数论(最大公约数、最小公倍数)等,这些都是常见的考点。 首先,JAVA C组的题目通常难度适中,侧重基础算法和编程能力。可能包括模拟、排序、搜索、动态规划、数论、字符串处理、贪心算法等。样题需要覆盖这些方面,同时结合蓝桥杯喜欢出的实际应用题,比如日期计算、路径问题、数学建模等。 接下来,我需要考虑近的趋势,比如2021和2022的题目,是否有新增的题型或重点。例如,引用[1]中提到STL容器去重和模拟题,引用[2]中的Floyd算法用于路径问题。JAVA中对应的数据结构如HashSet、ArrayList等可能被考察。 样题设计方面,应该包括不同类型的题目,如填空题、编程题,并覆盖不同的算法。例如,日期问题、最短路径、动态规划、数论题、字符串处理、贪心算法、回溯、位运算、图遍历、模拟题等。每个样题需要给出题解,并注意使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$。 然后,我需要确保题解代码用JAVA编写,符合C组的难度,并注意注释和代码结构的清晰。同时,引用提供的资料中提到的思路,比如使用Floyd算法,可以转化为JAVA代码,并解释算法原理。 最后,生成相关问题,可能涉及各个样题的扩展,比如不同算法的应用、优化方法、复杂度分析等。需要确保问题与样题相关,帮助用户深入理解考点。</think>根据蓝桥杯JAVA C组历真题分析[^1][^2],2025可能延续基础算法+实际应用的命题模式。以下是预测的10类题型及样题解析: --- ### 一、日期计算(模拟题) **样题**:计算从1949-10-01到2025-05-01之间有多少个"月份首日为周一"的日期 **题解**: ```java import java.util.Calendar; public class DateCount { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); cal.set(1949, Calendar.OCTOBER, 1); int count = 0; while(cal.get(Calendar.YEAR) <= 2025) { if(cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY && cal.get(Calendar.DAY_OF_MONTH) == 1 && cal.get(Calendar.YEAR) >= 1949) { count++; } cal.add(Calendar.MONTH, 1); } System.out.println(count - 1); // 减去初始化的1949-10-01 } } ``` **核心**:Calendar类的灵活使用,注意月份从0开始 --- ### 二、最短路径问题(Floyd算法) **样题**:节点数为$n$的图中,若两节点编号绝对值差≤20则边权为$lcm(i,j)$,求1到n的最短距离 **题解**: ```java public class Floyd { static long[][] dist; static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } static int lcm(int a, int b) { return a * b / gcd(a, b); } public static void main(String[] args) { int n = 2025; dist = new long[n+1][n+1]; // 初始化邻接矩阵 for(int i=1; i<=n; i++){ Arrays.fill(dist[i], Long.MAX_VALUE/2); dist[i][i] = 0; for(int j=Math.max(1,i-20); j<=Math.min(n,i+20); j++){ if(i != j) dist[i][j] = lcm(i,j); } } // Floyd核心 for(int k=1; k<=n; k++) for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) dist[i][j] = Math.min(dist[i][j], dist[i][k]+dist[k][j]); System.out.println(dist[1][n]); } } ``` **关键点**:处理大数时使用`Long.MAX_VALUE/2`防止溢出[^2] --- ### 三、动态规划(背包问题变种) **样题**:给定硬币面值数组coins,求恰好组成金额M的方案数(1 ≤ M ≤ 1e5) **状态转移方程**: $$ dp[i][j] = dp[i-1][j] + dp[i][j-coins[i]] $$ **优化解法**: ```java public int coinChange(int[] coins, int amount) { int[] dp = new int[amount+1]; dp[0] = 1; for(int coin : coins) { for(int j=coin; j<=amount; j++) { dp[j] += dp[j - coin]; } } return dp[amount]; } ``` --- ### 四、数论题(质因数分解) **样题**:求$1!$到$n!$中所有数末尾连续零的数量之和 **数学原理**:阶乘末尾零的数量由$min(\lfloor n/5 \rfloor + \lfloor n/25 \rfloor + ...)$决定 **核心代码**: ```java int count = 0; for(int i=5; i<=n; i*=5) count += n/i; ``` --- ### 五、字符串处理(正则表达式) **样题**:验证IPv4地址有效性,需处理0-255及前导零限制 **正则表达式**: ```java String pattern = "^((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)(\\.(?!$))?){4}$"; ``` --- ### 六、贪心算法(区间调度) **样题**:选择最多不重叠区间,按结束时间排序后遍历: ```java Arrays.sort(intervals, (a,b)->a[1]-b[1]); int count = 0, end = -1; for(int[] itv : intervals) { if(itv[0] >= end) { count++; end = itv[1]; } } ``` --- ### 七、回溯算法(排列组合) **样题**:生成1-n的所有排列且相邻元素差≥2 **剪枝策略**: ```java void backtrack(List<Integer> path, boolean[] used) { if(path.size() == n) { res.add(new ArrayList<>(path)); return; } for(int i=1; i<=n; i++) { if(!used[i] && (path.isEmpty() || Math.abs(i-path.getLast())>=2)) { used[i] = true; path.add(i); backtrack(path, used); path.removeLast(); used[i] = false; } } } ``` --- ### 八、位运算(状态压缩) **样题**:用二进制表示开关状态,判断能否通过操作达到全亮 **技巧**: ```java int mask = 0; for(int i=0; i<n; i++) if(light[i]) mask |= 1 << i; ``` --- ### 九、图的遍历(DFS/BFS) **样题**:岛屿最大面积问题,典型BFS解法: ```java int[] dx = {1,-1,0,0}; int[] dy = {0,0,1,-1}; Queue<int[]> q = new LinkedList<>(); q.offer(new int[]{x,y}); visited[x][y] = true; while(!q.isEmpty()) { int[] pos = q.poll(); // 处理四个方向... } ``` --- ### 十、模拟题(大数运算) **样题**:实现大整数加法(超过long范围) **核心逻辑**: ```java StringBuilder res = new StringBuilder(); int carry = 0; for(int i=num1.length()-1, j=num2.length()-1; i>=0 || j>=0 || carry>0; i--,j--) { int n1 = i>=0 ? num1.charAt(i)-'0' : 0; int n2 = j>=0 ? num2.charAt(j)-'0' : 0; int sum = n1 + n2 + carry; res.append(sum % 10); carry = sum / 10; } return res.reverse().toString(); ``` --- 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值