wrong answer 很多情况下是因为题目没看清楚

博客指出在某些情况下,反复看代码并无作用,强调平时要注意相关要点,但未明确具体要点内容。

在这种情况下,看再多遍代码也没用。

平时要注意这一点哭

2. 打怪兽 题目ID:19391拓展题100分 最新提交: Wrong Answer 30 分 历史最高: Wrong Answer 30 分 时间限制: 1000ms 空间限制: 262144kB 题目描述 在一条长廊上依次排列了 � n 只怪兽,标号为 1 1 到 � n。 第 � i 只怪兽的“战力”为 � � a i ​ ,可能是正数、负数或零。 英雄最初战力为 0 0 ,一开始站在第 � m 只怪兽面前。他在首次站到某只怪兽面前时,需要攻打该怪兽,攻打的结果会将该怪兽的战力(正或负)加入到自己的战力中。任意时刻,英雄的战力都不能小于 0 0。 英雄可以选择向左或向右移动(每次只能移动到相邻怪兽面前),问能否从位置 � m 开始,攻打到最左边的怪兽(标号 1 1)或者最右边的怪兽(标号 � n)。 若英雄能在攻打到怪兽 1 1 或怪兽 � n,且此时英雄战力仍然不小于 0 0 ,则输出 YES,否则输出 NO。 输入格式 题目共有 � t 组样例。 第一行输入一个正整数 � t,表示样例的组数。 对于每组样例的第一行输入两个整数 � n 和 � m。 每组样例的第二行输入 � n 个整数,依次表示 � 1 , � 2 , … , � � a 1 ​ ,a 2 ​ ,…,a n ​ 。 输出格式 对于每组样例,单独输出一行。若可以到达最左或最右端,输出 YES;否则输出 NO。 样例 Input 1 1 6 5 -24 11 -15 -32 7 -4 Output 1 YES 数据范围 对于其中 20 % 20% 的数据, 1 ≤ � ≤ 1 0 5 1≤n≤10 5 , − 1 0 9 ≤ � � ≤ 1 0 9 −10 9 ≤a i ​ ≤10 9 , 1 ≤ � ≤ � � � ( � , 10 ) 1≤m≤min(n,10); 对于另 30 % 30% 的数据, 1 ≤ � ≤ 1 0 3 1≤n≤10 3 , − 1 0 9 ≤ � � ≤ 1 0 9 −10 9 ≤a i ​ ≤10 9 , 1 ≤ � ≤ � 1≤m≤n; 对于 100 % 100% 的数据, 1 ≤ � ≤ 1 0 5 1≤n≤10 5 , − 1 0 9 ≤ � � ≤ 1 0 9 −10 9 ≤a i ​ ≤10 9 , 1 ≤ � ≤ � 1≤m≤n, 1 ≤ � ≤ 10 1≤t≤10。 附件 使用单调栈,单调队列 给出C++题解
03-09
<think>嗯,用户之前提供的代码在OJ系统上出现了错误,特别是闰年判断和星期计算的问题。我得仔细分析哪里出错了。首先,原代码中的月份计算可能有问题。比如,月份数组是{31,28,31,...},当处理闰年二月的时候,是否正确地修改了天数?比如,在闰年,二月应该是29天,原代码里在循环中判断month是否为1(即二月)时,将天数设为29。这看起来是对的。然后是年份计算部分。原代码中,年份从2000年开始,每次减去整年的天数,直到剩余天数不足一年。这部分逻辑是否正确?比如,如果剩余天数正好等于一年的天数,应该进入下一年吗?比如,假设remaining是366天,而当前年是闰年,那么remaining减去366天后,年份加1。这问题,因为剩下的天数已经不足以构成新的一年了。接下来是月份的计算。原代码中的循环从0到11,依次减去每个月的天数。当月份是二月时,如果是闰年,天数设为29。这一步是否正确?是的。但有一个可能的错误点:remaining在减去某个月的天数后,是否会导致月份索引错误?比如,假设remaining在减去某个月的天数后刚好等于0,这时候应该视为该月的最后一天。例如,如果remaining是30天,某个月有30天,那么remaining变成0,月份应该是该月,日期是该月的30日。但在代码中,remaining被减之后,如果remaining>= dim,则继续循环。否则,break。所以比如,当remaining是30,dim是30,那么remaining>= dim成立,会减去30,remaining变为0,然后继续下一个月份的循环。这时候月份会变成下一个,导致错误。比如,假设是1月(31天),remaining是31,减去后remaining为0,循环继续,month增加到1,然后检查剩余天数是否>=2月的天数。这时候remaining已经是0,所以break。此时月份是1(即二月),日期是0+1=1日?这显然不对。正确的逻辑应该是,当remaining>= dim时,才减去,否则该月就是当前月,日期是remaining+1。例如,原代码中的循环:for (month =0;month <12; month++) {intdim =months[month];if(month==1 &&leap)dim =29;if (remaining >=dim){remaining -=dim;}else break; }假设remaining是30,dim是30,那么条件成立,remaining变为0,然后继续循环,month变为1,进入下一个循环。此时,dim是2月的天数,比如28或者29。此时remaining是0,条件不成立,break。此时month是1,即二月。而日期是0+1=1日。所以正确。比如,假设输入是31天,那么:2000年1月有31天,remaining初始是31。进入循环,month=0,dim=31。remaining >=31,所以减去31,remaining=0。然后循环继续,month++变为1。此时,检查remaining是否>=dim(此时是28或29)。因为remaining是0,所以break。此时month=1,日期是0+1=1。所以结果是2000-02-01。这正确。所以这个部分的逻辑是正确的? 但可能存在问题的情况是,当remaining刚好等于某个月的天数时,会进入下个月,导致日期变成下个月的第一天。例如,假设remaining是31天,那么处理后是2月1日,而不是1月31日后的第二天。这显然错误。比如,输入n=31天,那么从2000-01-01开始加上31天,应该是2000-02-01吗?不,应该是2000-02-01吗?原题中的样例输入中有1730天,输出是2004-09-26。需要验证原代码是否正确。 所以,原代码中的月份处理逻辑是否正确? 比如,当remaining等于某个月的天数时,remaining会被减去该月的天数,导致remaining变为0,然后月份递增,但此时月份循环会继续到下一个月份,然后在下一个月份的条件判断中,remaining为0,无法满足>=dim的条件,因此break。此时月份是当前循环的month,即原月份的下一个,而日期是0+1=1日。例如,假设remaining等于31天(一月),那么处理后变成2月1日。但正确的情况应该是1月31日后的第二天是2月1日,所以正确。例如,n=30天:2000-01-01加上30天是2000-01-31?或者2000-01-31是初始日期后的30天吗?比如,第一天是0天,所以n=0是2000-01-01,n=30天是2000-01-31。是的。所以原代码中,当remaining是30时,月份循环处理如下: month=0,dim=31。判断30>=31?否,所以break。此时月份是0(即一月),日期是30+1=31日。正确。那之前的例子中,如果remaining等于dim的话,比如dim=30天,remaining是30,那么条件成立,减去,remaining变为0,month++,进入下一个循环。例如,假设是四月(30天),remaining=30。此时,month=3(数组索引是3对应四月?因为数组索引0是1月)。假设当前是四月,dim=30。remaining=30>=30,减去,remaining=0,month++变为4(五月),然后检查五月天数31。此时remaining=0,无法满足条件,break。所以月份是4+1=5月?而日期是0+1=1日。那这种情况下,正确的日期应该是四月的30日后的第二天,即五月1日。所以原代码的处理是正确的。那问题可能出在哪里?另一个可能的问题是闰年判断。例如,1700年是否是闰年?根据题目中的闰年规则,能被4整除但不能被100整除,或者能被400整除。所以1700能被100整除但不能被400整除,所以不是闰年。原代码中的is_leap函数是否正确?是的,函数返回(year%4==0 &&year%100!=0)|| (year%400==0)。这正确。 另一个问题可能是星期计算。原代码中,星期几的计算是(6 +n)%7。因为2000-01-01是星期六,所以初始的星期是6(假设数组顺序是Sunday到Saturday的话?)。原代码中的weekdays数组是{"Sun","Mon", "Tue","Wed", "Thu","Fri", "Sat"}。索引0是Sun,1是Mon,依此类推。所以星期六对应的是索引6。假设n=0天,即初始日期,星期六应该是索引6。计算方式:(6 +0)%7=6,正确。例如,样例输入中的1730天后的输出是Sunday。原代码中的计算是否正确? 计算样例输入中的第一个测试用例:1730天后的日期是否正确? 根据样例输出,1730天后的日期是2004-09-26,星期日。原代码的weekday计算是(6+1730)%7= (1736) %7。计算1736 ÷7是多少?7*248=1736,余0。所以0对应的是Sunday吗?原数组中的索引0是"Sun",所以正确。所以样例中的输出是正确的。那为什么OJ会返回错误? 可能的错误点:1.月份的输出是否正确?原代码中month变量在循环结束后是索引,从0开始。例如,循环结束后month的值是8(索引从0开始,比如0是1月,到1112月),那么输出是month+1=9,即九月。这正确。例如样例中的2004-09-26,月份是9,正确。2.日期是否正确?原代码中remaining+1是否正确?例如,假设remaining在循环结束后是25,那么日期是26日。比如样例中的1730天后的情况,假设remaining是25,则输出26日。这正确。那问题可能出在闰年判断或者月份天数计算。例如,在跨越闰年的时候,是否处理正确?比如,假设某一年是闰年,例如2000年,那么处理是否正确?比如,2000年是闰年,所以二月份有29天。原代码中处理正确。例如,计算2000年后的天数是否正确? 另一个可能的错误点是,当剩余天数刚好等于一年的天数时,是否将年份递增。例如,假设剩余天数是365天,而当前年不是闰年,那么应该减去365天,年份加1。例如,假设n=365天,那么日期应该是2001-01-01?原代码中,处理如下:在年份循环中,判断当前年的天数,如果remaining>= days_in_year,则减去,年份加1。例如,假设remaining=365,当前年是2000年(闰年,366天),则条件不成立,跳出循环。所以年份保持2000年。然后处理月份。这时候,remaining是365天?这显然不对,因为2000年是闰年,总共有366天。所以当n=365天时,应属于2000年内的天数。例如,2000-12-31是365天后的日期。那原代码中的年份循环是否正确?例如,假设输入n=366天,那么年份应该是2001年。原代码中的处理:在年份循环中,days_in_year=366(2000年是闰年),remaining>=366?是的,所以减去366,remaining=0,年份变为2001。然后处理月份,此时remaining=0,所以月份循环中,每个月的天数都会被比较。例如,month=0(一月),dim=31。remaining=0>=31?否,所以break。此时月份是0,日期是0+1=1。所以日期是2001-01-01。正确。那另一个测试用例:n=365天。此时,年份循环中,2000年的days_in_year是366。remaining=365<366,所以年份保持2000年。然后处理月份。剩余天数是365天。需要逐月减去。例如,各个月的天数总和是366天(闰年),所以365天应该属于该年的最后一天,即2000-12-31。原代码中的处理是否正确?例如,月份循环: month从0开始,依次处理每个月的天数:1月31天:remaining >=31 →是,减去31,remaining=3342月29天(闰年):是,减去29→3053月31 →305-31=2744月30→274-30=2445月31 →244-31=2136月30→213-30=1837月31183-31=1528月31152-31=1219月30 →121-30=9110月31→91-31=6011月30 →60-30=3012月31→30 >=31?否,所以break。此时month=11(即12月),日期是30+1=31日。所以总日期是2000-12-31,正确。这正确。那原代码中的月份处理逻辑是正确的? 可能的问题在于星期计算。原代码中的weekdays数组是否正确?例如,用户给出的样例输出中,1730天后的星期是Sunday。原代码计算的是(6+1730) %7 =1736%7=0,对应数组中的索引0,即"Sun"。正确。样例输出中的第一个测试用例的输出正确,所以这说明原代码中的星期计算是对的? 那为什么OJ会给出Wrong Answer?可能还有其他错误,比如:-多组输入的处理是否正确?原代码中的循环条件是while(scanf("%d", &n)!= EOF),当输入-1时,如何处理?例如,样例输入的最后一行为-1,用户不需要处理。原代码中的循环在读取到-1时,会进入循环体,但此时如何处理? 例如,输入-1时,原代码会执行年份计算,但根据题目要求,输入-1时不需要处理。所以,原代码中的循环条件是否有问题?原代码中的循环条件是:while (scanf("%d",&n) !=EOF){处理n... }当输入-1时,scanf会读取到n=-1,进入循环体,然后进行处理。但是根据题目要求,当输入是-1时,不需要处理。因此,在代码中应该检查n是否为-1,如果是则跳过处理。否则继续。所以,原代码中的循环有处理n=-1的情况,导致当输入-1时,程序仍然会进行计算,从而输出错误的结果。例如,样例输入中的最后一行是-1,程序会处理它,导致错误。例如,样例输入中的测试用例:输入包括:1730174017501751-1原代码在处理-1时,进入循环,执行年份计算。此时,n=-1,导致年份从2000年开始,计算天数-1,这显然会导致错误。例如,remaining =-1,年份循环中,days_in_year=365或366,remaining是-1,无法进入循环,所以年份保持2000年。然后处理月份时,remaining=-1,导致错误。所以,输出的结果会是错误的日期,并且程序会处理-1的情况,而题目要求不处理。因此,原代码中的循环条件应该改为:当输入的n不等于-1时才处理。例如:while (scanf("%d",&n) ==1&& n!= -1){//处理} 或者在循环内部,首先检查n是否为-1,如果是则break。例如,修改后的代码:while(scanf("%d", &n)!= EOF) {if(n== -1)break;//处理}这样,当输入-1时,循环会终止,不处理该输入。 原代码中的循环有这样的判断,导致处理了-1的情况,从而产生错误输出。这是导致OJ返回Wrong Answer的一个原因。 另外,原代码中输出星期几的部分是否正确?原代码中的weekdays数组是:const char* weekdays[]= {"Sun","Mon", "Tue","Wed", "Thu","Fri", "Sat"}; 但题目要求输出的星期几是全称,例如"Sunday",而不是缩写。例如,样例输出中的第一个结果是"Sunday",而原代码输出的是"Sun",这显然不符合题目要求。因此,这是导致WrongAnswer的主要原因。 例如,样例输入中的1730天后的输出应为"Sunday",而原代码输出的是"Sun",所以格式错误,OJ系统会判为错误。 因此,需要将weekdays数组中的元素改为全称:const char* weekdays[]= {"Sunday","Monday", "Tuesday","Wednesday", "Thursday","Friday", "Saturday"}; 同时,计算星期几的方式是否正确?原代码中的计算式是:weekday= (6 +n)%7;例如,n=0时,6%7=6,对应索引6,数组中的元素是"Saturday"吗?原数组在修改前是"Sun","Mon"等,索引0对应Sunday。如果修改后的数组顺序是否正确? 假设修改后的数组是:索引0对应Sunday,索引1对应Monday,依此类推,索引6对应Saturday。那么,当n=0时,星期六应位于索引6。原计算式是(6+0) %7=6,对应索引6是Saturday,正确。例如,样例输入中的1730天后的星期是Sunday,根据计算式: (6+1730) %7 =1736%7。计算7*248=1736,余0,所以索引0对应Sunday,正确。 所以,修改weekdays数组的元素为全称,并确保顺序正确,可以解决这个问题。 另外,原代码中的输出格式是否正确?题目要求输出格式为"YYYY-MM-DDDayOfWeek",例如"2004-09-26Sunday"。原代码中的printf语句:printf("%04d-%02d-%02d%s\n",year,month +1,remaining +1, weekdays[weekday]); 其中,月份和日期的格式是否正确?例如,month+1如果是9,则输出09,正确。日期是remaining+1,如果是26,则输出26,正确。星期部分在修改数组后正确。 综上所述,原代码存在两个主要问题:1.处理了输入为-1的情况,导致输出错误。2.星期几的输出使用了缩写而非全称,导致格式错误。 此外,需要检查闰年判断是否正确,但原函数是正确的。月份和日期的计算逻辑是否正确,经过分析是正确的。因此,修改这两个问题应该能通过OJ测试。</think>### 问题分析 原代码存在两个关键错误导致OJ系统判错: 1. **未正确处理终止条件**:未过滤输入为-1的情况,导致处理了非法数据 2. **星期名称格式错误**:题目要求输出全称但代码中使用缩写 ### 修正代码 ```c #include <stdio.h> int is_leap(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } const char* weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; int main() { int months[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int n; while (scanf("%d", &n) == 1 && n != -1) { // 修正1:过滤-1输入 int year = 2000; int remaining = n; // 年份计算 while (1) { int days_in_year = is_leap(year) ? 366 : 365; if (remaining >= days_in_year) { remaining -= days_in_year; year++; } else break; } // 月份计算 int month; int leap = is_leap(year); for (month = 0; month < 12; month++) { int dim = months[month]; if (month == 1 && leap) dim = 29; if (remaining >= dim) { remaining -= dim; } else break; } // 结果输出 int weekday = (6 + n) % 7; printf("%04d-%02d-%02d %s\n", year, month + 1, remaining + 1, weekdays[weekday]); // 修正2:使用全称星期名 } return 0; } ``` ### 关键修正点说明 | 错误类型 | 原代码问题 | 修正方案 | |---------|-----------|---------| | 输入处理 | 未过滤-1导致错误计算 | 添加`&& n != -1`条件 | | 格式错误 | 星期输出使用缩写 | 修改数组为全称星期名称 | ### 验证样例 输入: ``` 1730 1740 1750 1751 -1 ``` 输出: ``` 2004-09-26 Sunday 2004-10-06 Wednesday 2004-10-16 Saturday 2004-10-17 Sunday ``` ### 算法复杂度 - 时间复杂度:$O(y + m)$,其中y为年份跨度,m为月份跨度 - 空间复杂度:$O(1)$,仅使用固定大小数组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值