Codechef BUYING2代码报错,求遗漏测试用例及初学者优化建议
嘿,我来帮你排查这个问题!首先咱们先理清你的代码里的逻辑错误,以及遗漏的测试用例,再给你一些适合初学者的优化建议。
首先,你的代码核心逻辑存在对题目的误解,这是导致答案错误的主要原因。先明确BUYING2问题的核心要求:
Chef可以选择买所有糖果袋,或者买所有袋子除了一个。要求买的袋子的总糖果数必须是X的倍数,且这个总数尽可能大。如果没有这样的正总数(即所有可能的购买组合的总和都不是X的倍数),输出-1。
你的当前逻辑是:计算所有袋子的总和sum1,取sum1//X作为s,余数r=sum1%X,然后判断r是否小于等于最小的袋子a[0]——如果是就输出s,否则输出-1。这个逻辑完全不符合题目要求,因为只有当sum1 - a[i]能被X整除时,去掉a[i]才是有效的,而不是r<=a[i]。
以下是你代码无法正确处理的典型测试用例:
测试用例1:余数r存在对应a[i]满足a[i] ≡ r mod X,但a[i] > r
输入:1 3 7 9 3 4总和
sum1=16,r=16%7=2。你的代码会因为r=2<=最小袋子3,输出16//7=2,但实际情况是:- 买所有袋子总和16,不是7的倍数;
- 去掉9后总和7,是7的倍数,对应答案1;
- 去掉3或4后的总和都不是7的倍数;
正确答案是1,但你的代码输出2,导致错误。
测试用例2:总和本身不能被X整除,但存在某个a[i]使得sum1 -a[i]能被X整除,且a[i]不是最小的袋子
输入:1 4 5 6 7 3 4总和
sum1=20?不,换总和sum1=21,X=5,r=1。袋子中有6(6%5=1),此时sum1-6=15,能被5整除,答案是3。你的代码排序后a[0]=3,r=1<=3,输出21//5=4,但实际sum1-3=18不是5的倍数,正确答案是3,你的代码输出错误。测试用例3:n=1时,袋子数量无法被X整除的情况
输入:1 1 10 5你的代码判断
5//10=0 <1,输出-1。但根据题目要求,如果允许买0个(总和0是X的倍数),答案应该是0;如果题目要求必须买正数量,输出-1。而题目样例3输入1 10 12输出1,说明你可能把题目理解成了“买任意数量的袋子,取最大的不超过总和的X的倍数”,这和原题要求完全不同,也是你代码错误的根源。
作为编程初学者,你的代码在结构、效率和可读性上都有改进空间,结合正确的逻辑,给出以下建议:
1. 修正核心逻辑
按照题目正确要求,代码逻辑应该是:
#include <stdio.h> #include <limits.h> int main() { int t; scanf("%d", &t); while (t--) { int n, x; scanf("%d %d", &n, &x); int a[101]; long long sum_total = 0; // 用long long避免总和溢出 for (int i = 0; i < n; i++) { scanf("%d", &a[i]); sum_total += a[i]; } int max_ans = -1; // 先检查买所有袋子的情况 if (sum_total % x == 0) { max_ans = sum_total / x; } // 检查去掉每个袋子的情况 for (int i = 0; i < n; i++) { long long current_sum = sum_total - a[i]; if (current_sum == 0) continue; // 不买任何袋子,题目可能不允许 if (current_sum % x == 0) { int current_ans = current_sum / x; if (current_ans > max_ans) { max_ans = current_ans; } } } printf("%d\n", max_ans); } return 0; }
2. 效率优化
- 你的代码中使用了冒泡排序,时间复杂度是O(n²),但实际上我们不需要排序,只需要遍历每个袋子检查
sum_total -a[i]是否能被X整除即可,时间复杂度降到O(n),更高效。 - 使用
long long存储总和,避免当n较大、a[i]较大时出现整数溢出的问题。
3. 代码可读性优化
- 变量命名更清晰:比如
sum_total代替sum1,max_ans代替s,让代码更容易理解。 - 去掉不必要的分支:比如不需要单独处理n=1的情况,统一逻辑即可。
- 注释关键步骤,方便自己和他人阅读代码。
4. 边界情况处理
- 考虑总和为0的情况(比如所有袋子都被去掉,但题目不允许买0个,所以要跳过)。
- 考虑整数溢出:当n=100,每个a[i]=1e9时,总和会超过int的范围(int最大约2e9),所以用long long存储总和是必要的。
内容的提问来源于stack exchange,提问作者Alpha

