在线编译器 C

#include <stdio.h> unsigned long long grains(unsigned long long n) { unsigned long long sum=1; unsigned long long i=1; while(i<=n){ sum=sum*2; i++; } sum=sum/2; return sum; } int main() { unsigned long long x,answer; scanf("%llu",&x); answer = grains(x); printf("%llu",answer); return 0; }
这段代码的功能是计算棋盘上第 n 个格子上的麦粒数(国际象棋棋盘麦粒问题,每个格子是前一个格子的两倍,第一个格子是1粒)。函数 `grains` 试图返回第 n 个格子的麦粒数,但实现中存在逻辑问题。

- 你的循环从 i=1 开始,每次将 sum 乘以 2,循环结束后又除以 2。这样实际上计算的是 2 的 n 次方,但第一个格子应该是 1(即 2 的 0 次方),而你的结果会变成 2 的 n-1 次方。检查一下循环的初始值和结束条件是否与你的意图一致。
- 注意当 n=1 时,你的代码会先执行一次循环(sum 变成 2),然后除以 2 得到 1,结果正确。但当 n=2 时,循环两次后 sum=4,除以 2 得 2,而正确结果应该是 2(第二个格子有2粒),这似乎也正确。但仔细推敲,你的循环逻辑实际上计算的是 2 的 n 次方再除以 2,即 2 的 n-1 次方,对于 n=1 和 n=2 恰好正确,但对于更大的 n 是否仍然符合题意?请重新思考每个格子麦粒数的定义:第一个格子是 1 粒,第二个是 2 粒,第三个是 4 粒……第 n 个格子是 2 的 (n-1) 次方。你的代码是否直接对应这个公式?