问题描述
输入输出
解题思路
这道题确实有点难顶,看了下是蓝桥杯省赛pythonA组和C/C++研究生组的题。
这道题很容易超时,所以用模拟的话基本写不了(至少我不会),起初我是用bfs模拟,用一个队列去一个节点一个节点的跑,果然,超时了一半样例(代码放后后面)。
最开始还想过要不要建树..........还好否决了
后面用一层一层往下,读取该子树每一层的最左边和最右边的节点进行判断的方法做出来的。
但是,但是!!!期间有很长的一段时间,都有一半样例超时。我以为是算法设计的问题,一直在想着怎么优化。
结果,结果!!!!!竟然把int改成long就好了…………………………唉
虽然花了很多时间在偏的方向上面,不过也算学到了经验:当前面样例过了,后面样例超时的时候,不一定是因为算法复杂度高需要优化,也可能是数据爆了导致运行到了一个深坑里。
以防万一的话,以后遇到可能爆的变量还是用long好了。
AC代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long t, n, m, k;
t = scan.nextInt();
while (t-- > 0) {
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
int ans = 1; // 初始化答案为1,因为第一个点一定符合条件
long left = m * k - m + 2; // 计算当前区间的左边界
long right = m * k + 1; // 计算当前区间的右边界
// 使用循环计算区间内符合条件的点的数量
while (right < n) {
ans += right - left + 1; // 更新答案
left = m * left - m + 2; // 计算下一个区间的左边界
right = m * right + 1; // 计算下一个区间的右边界
}
// 处理边界情况
if (right == n) {
ans += right - left + 1; // 更新答案
} else if (right > n && n >= left) {
ans += n - left + 1; // 更新答案
}
System.out.println(ans); // 输出答案
}
}
}
模拟代码(只过了一半)
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long t, n, m, k;
Queue<Long> queue = new LinkedList<>();
t = scan.nextInt();
while (t-- > 0) {
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
long ans = 1; // 初始化答案为1,因为第一个点一定符合条件
queue.add(k); // 将起始点加入队列
// 使用队列进行广度优先搜索
while (!queue.isEmpty()) {
k = queue.poll(); // 出队列
for (long i = m * k - m + 2; i <= n && i <= m * k + 1; i++) {
ans++; // 更新答案
queue.add(i); // 将下一个点加入队列
}
}
System.out.println(ans); // 输出答案
}
}
}
相关知识
规律&思维
(by 归忆)