很快的代码
2026-03-25 18:41:52
发布于:甘肃
0阅读
0回复
0点赞
#include <unistd.h>
int read_int() {
char buf[16];
int n = read(0, buf, 16);
int x = 0;
for (int i = 0; i < n && buf[i] >= '0'; ++i)
x = x * 10 + (buf[i] - '0');
return x;
}
void write_long(long long x) {
char buf[32];
int i = 31;
buf[31] = '\n';
do {
buf[--i] = '0' + (x % 10);
x /= 10;
} while (x);
write(1, buf + i, 32 - i);
}
int main() {
int k = read_int();
int lo = 1, hi = 2e9;
while (lo < hi) {
int mid = lo + (hi - lo + 1) / 2;
if ((long long)mid * (mid + 1) / 2 <= k)
lo = mid;
else
hi = mid - 1;
}
int m = lo;
long long total = (long long)m * (m + 1) * (2 * m + 1) / 6;
total += (long long)(k - m * (m + 1) / 2) * (m + 1);
write_long(total);
return 0;
}
代码详解
- 头文件与输入输出
#include <cstdio>:只引入 C 标准 I/O,没有 C++ 流对象的全局构造开销,内存占用极小。
scanf 读取整数,比 cin 更快。
手写 write 函数递归输出数字,调用 putchar,比 printf 更轻量。
- 二分查找 m
下界 lo = 1(m 至少为 1),上界 hi = 2e9(足够大,因为当 k 最大时 m 约
2
k
2k
,远小于 2e9)。
循环条件 lo < hi,采用“左边界向右逼近”的写法。
mid = lo + (hi - lo + 1) / 2:上取整,避免当 lo 和 hi 相邻时陷入死循环。
判断 mid * (mid + 1) / 2 <= k 时,注意乘法可能溢出 32 位 int,所以强制转换为 long long。
如果条件成立,说明 mid 可行,将 lo 设为 mid;否则 hi = mid - 1。
循环结束后 lo 即为最大满足条件的 m。
- 计算总金币
第一部分:平方和公式,直接计算前 m 个阶段的总金币。
第二部分:剩余天数乘以 (m+1),注意 k - m*(m+1)/2 可能为 0,不影响。
所有乘法都用 long long 保证中间结果不溢出(k ≤ 10^9 时总金币约 10^18,仍在 long long 范围内)。
- 输出
调用 write(total) 输出结果,没有换行(题目不要求,但可自行添加 putchar('\n'))。
这里空空如也


有帮助,赞一个