竞赛用Python代码优化求助:CodeChef Number Game超时问题
如何优化Python代码通过CodeChef Number Game的时间限制
当然可以在Python 3里解决这个问题!既然你的C++代码已经通过,说明核心算法逻辑完全正确,只是Python的一些固有开销和代码写法拖慢了速度。只要针对性做一些常数级优化,就能把速度提上去达到时限要求。下面是几个关键优化方向,结合问题场景给你具体建议:
1. 彻底优化输入输出
Python默认的input()和print()函数在处理大量测试用例时速度极慢,这是超时的重灾区之一。换成一次性读取所有输入,再批量处理输出,能节省大量时间:
import sys def main(): # 一次性读入所有输入,拆分后处理 all_input = sys.stdin.read().split() # 假设第一个数是测试用例数量,后面是每个测试用例的n t = int(all_input[0]) test_cases = list(map(int, all_input[1:t+1])) # 处理逻辑... # 把所有结果存到列表,最后一次性输出 results = [] for n in test_cases: results.append("WIN" if is_winning(n) else "LOSE") sys.stdout.write('\n'.join(results) + '\n') if __name__ == "__main__": main()
2. 预处理所有可能的结果(而非逐个计算)
如果题目中n的范围有上限(比如1e5或1e6),提前预处理出所有n对应的结果,测试用例直接查表即可,这会把每个测试用例的时间复杂度降到O(1)。比如针对Number Game的经典规则(轮流减平方数,无法操作则输),预处理代码可以这样写:
import sys def main(): all_input = sys.stdin.read().split() t = int(all_input[0]) test_cases = list(map(int, all_input[1:t+1])) max_n = max(test_cases) # 预生成所有可能用到的平方数 max_square_root = int(max_n ** 0.5) squares = [x*x for x in range(1, max_square_root + 1)] # 初始化DP数组,dp[i]表示数字i是否是先手必胜态 dp = [False] * (max_n + 1) for i in range(1, max_n + 1): for s in squares: if s > i: break # 平方数超过当前i,不用继续检查 if not dp[i - s]: dp[i] = True break # 找到一个必败态的前驱,直接标记为必胜态 # 生成结果 results = ["WIN" if dp[n] else "LOSE" for n in test_cases] sys.stdout.write('\n'.join(results) + '\n') if __name__ == "__main__": main()
这里的关键是:循环中一旦找到符合条件的平方数就break,避免不必要的计算;同时用数组存储状态,比递归记忆化的开销小得多。
3. 消除递归开销(如果用了递归)
Python的递归调用开销远大于迭代,如果你的原始代码用了递归记忆化(比如lru_cache),换成迭代的动态规划是必须的。即使加了lru_cache,递归的函数调用栈开销还是会拖慢速度,迭代的DP数组在速度上会有明显提升。
4. 其他小细节优化
- 用局部变量代替全局变量:Python中局部变量的访问速度比全局变量快,所以在函数内部把常用的变量(比如平方数列表)赋值给局部变量,能减少访问时间。
- 避免重复计算:比如平方数列表只生成一次,不要在每个测试用例里重新计算。
- 减少类型转换:读入输入时直接转换成整数,不要反复做类型转换操作。
按照这些方法优化后,你的Python代码应该能达到CodeChef的时间限制。毕竟你的算法逻辑已经被C++验证过正确,只要把Python的常数开销降下来,就没问题了。
内容的提问来源于stack exchange,提问作者user144527
相关产品推荐
相关产品推荐

