编程竞赛高频考点

前言:考点技巧讲解 + 竞赛题实战


1.取位数

例如:123456

需求:取前三位和后三位

解:123456  /  1000 = 123

       123456 % 1000 = 456

工具一:取余 (% 10) —— “取尾”

规则: 一个数 % 10 的结果,永远是这个数的个位数(最右边的一位)。

  • 479 % 10 结果是 9

  • 47 % 10 结果是 7

  • 4 % 10 结果是 4

  • 12345 % 10 结果是 5

以此类推,想取后两位用%100,取后三位用%1000......

工具二:整除 (/ 10) —— “去尾”

规则: 一个整数 / 10 的结果,永远是这个数去掉个位数后剩下的部分。

  • 479 / 10 结果是 47 (小数点后的部分被丢弃了)

  • 47 / 10 结果是 4

  • 4 / 10 结果是 0

  • 12345 / 10 结果是 1234

以此类推,想取前几位,就可以用/10、/100......的方法将后几位剔除掉

 

思考:取位数的方法有很多,为什么要用数学方法来取?

1. 极致的性能(速度飞快)

% 和 / 是 CPU 的原生指令,是计算机硬件层面直接支持的运算。执行这些操作几乎不花费任何时间。

2. 极低的内存消耗

数学方法只使用了几个 int 变量,这些变量存储在一种叫做“栈”的高速内存区域中。而字符串方法创建了对象,这些对象存储在“堆”内存中,需要更复杂的内存管理(包括后续的垃圾回收)。简单说,数学方法几乎不占用额外内存

3. 通用性

无论你用 Java, C++, Python, JavaScript 还是任何主流编程语言,整数的取余和整除运算逻辑都是完全一样的。这是一个放之四海而皆准的计算机科学基础知识。学会了它,你就在所有语言中都掌握了处理数字位数的最佳方法。

 

考点竞赛题

问题描述

借书高峰期,人来人往,图书馆内的自动借书机前排起了长队。小蓝正在排队时突然被告知,需要快速确认自己借书卡编号是否有效。

自动借书机规定,每张借书卡编号都必须是 66 位数,为了简化检查,工作人员采用了这样的规则:借书卡编号的前三位数字之和必须等于后三位数字之和。若不满 66 位,自动在前面补零。

例如编号 45123,补零后为 045123

前三位数字为 045,和为 0+4+5=9;后三位数字为 123,和为 1+2+3=6;

两边和不相等,编号无效。

现在,给出小蓝的借书卡编号 NN,请你帮忙判断这个编号是否有效。

输入格式

输入一行,包含一个整数 NN,满足 0≤N<1060≤N<106。

输出格式

输出一行,如果编号有效,打印 YES;否则打印 NO

样例输入

123321

 

样例输出

YES

 

样例输入 2

23456

 

样例输出 2

NO

题解:

import java.util.Scanner;

public class Main3 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int N = scan.nextInt();
        scan.close();

        // 1. 将N地分为两部分
        int firstPart = N / 1000; // 对于45123,这里得到45
        int lastPart = N % 1000;  // 对于45123,这里得到123

        // 2. 分别计算各位之和,整数除法会自动处理“补零”
        int sumFirst = (firstPart / 100) + ((firstPart / 10) % 10) + (firstPart % 10);
        int sumLast = (lastPart / 100) + ((lastPart / 10) % 10) + (lastPart % 10);

        if (sumFirst == sumLast) {
            System.out.print("YES");
        } else {
            System.out.print("NO");
        }
    }
}

2.在两个数的和固定的条件下,如何组合这两个数,才能让它们的乘积取到最大值?

例如: 将数字10分成两个正整数。

需求: 如何分配这两个数,才能让它们的乘积最大?

解(实验法):

组合方式 (a, b)两数之和 (a+b)两数之积 (a*b)
(1, 9)101 * 9 = 9
(2, 8)102 * 8 = 16
(3, 7)103 * 7 = 21
(4, 6)104 * 6 = 24
(5, 5)105 * 5 = 25 (最大)

结论: 当两个数的和固定时,这两个数的值越接近(最理想是完全相等),它们的乘积就越大

策略:“均分策略” 算法

规则: 将一个总量 N 分成尽可能相等的两部分 a 和 b。

  • a = N / 2 (利用整数除法自动向下取整的特性)

  • b = N - a (剩下的部分)

例如:

  • N = 100: a = 50, b = 100 - 50 = 50。

  • N = 99: a = 49, b = 99 - 49 = 50。

思考:为什么要掌握这个数学模式?

1.识别问题本质 
很多竞赛题目(如切蛋糕、分配资源、安排任务)都是伪装。这个模式能帮助你迅速剥开故事外壳,看穿其“和定积最大”的数学内核。能识别出模式,问题就解决了一大半。

2.效率的巨大提升 (从 O(N) 到 O(1))

  • 暴力解法: 用一个 for 循环,尝试所有可能的组合(从 (0, N) 到 (N, 0)),找出最大值。时间复杂度是 O(N)
  • 数学优化解法: 直接运用“均分策略” (a = N/2; b = N-a;),一步到位算出最优组合。时间复杂度是 O(1)

考点竞赛题

问题描述

为了即将到来的蓝桥派对,小蓝准备了一个巨大的矩形蛋糕。他想把这个蛋糕切成尽可能多的块,以便分给更多的朋友。

小蓝手头有一把长刀,他总共可以切 NN 刀。他的切法有如下规则:

  1. 每一刀要么是“横切”(平行于蛋糕的某两条边),要么是“竖切”(与横切垂直)。
  2. 每一刀都必须笔直地从蛋糕的一条边切到其相对的另一条边。

现在,小蓝想知道,如何合理地分配这 NN 刀(即决定多少刀用于横切,多少刀用于竖切),才能使得最终得到的蛋糕块数量最多?请你帮助他计算出这个最大数量。

输入格式

输入的第一行包含一个整数 NN(1≤N≤1041≤N≤104),表示小蓝可以切的总刀数。

输出格式

输出一个整数,表示能够切出的最大蛋糕块数量。

样例输入

2

 

样例输出

4

题解:

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int count = scan.nextInt();
        int h = count / 2;
        int s = count - h;
        int cake = (h + 1) * (s + 1);
        System.out.print(cake);
        scan.close();
    }
}

未完待续......(OS:每日一更)

 

评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值