第 k 块恰好 k 天、每天 k 枚,用平方和公式求完整块贡献,再补尾块。
OJ: roj
题目 ID: 1100
难度:入门
标签:数学递推python
创建: 2026-09-29 18:51
更新: 2026-10-05 01:08
题目描述
国王按块发工资:第 1 块 1 天每天 1 枚,第 2 块 2 天每天 2 枚,第 3 块 3 天每天 3 枚,依此类推。给定天数
输入:一个整数 days。输出:累计金币数。
样例输入 6,输出 14。
思路
第 days 的最大完整块编号
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 18:52
# update_at: 2026-09-29 18:52
import sys
from math import isqrt
def full_blocks(days: int) -> int:
"""完整发放块的编号 n:第 k 块恰好占 k 天,1..n 块共 n(n+1)/2 天不超过 days。"""
return (isqrt(8 * days + 1) - 1) // 2 # 解 n^2+n-2*days <= 0,取最大整数根
def gold_coins(days: int) -> int:
"""前 days 天的金币总数:完整块用平方和公式,尾块按 n+1 枚金币补齐。"""
n = full_blocks(days)
tail_days = days - n * (n + 1) // 2 # 最后一个不完整块占用的天数
return n * (n + 1) * (2 * n + 1) // 6 + tail_days * (n + 1)
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
days = next(data)
print(gold_coins(days))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 01:08
* update_at: 2026-10-05 01:08
*/
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
ll days;
int main() {
scanf("%lld", &days);
// 前 n 个完整块共占 n(n+1)/2 天,求满足条件的最大 n
ll n = (ll)((sqrt(8.0 * days + 1.0) - 1.0) / 2.0);
// 修正浮点误差:若 (n+1)(n+2)/2 <= days,则 n 还可以加 1
while ((n + 1) * (n + 2) / 2 <= days) n++;
// 尾块剩余天数
ll r = days - n * (n + 1) / 2;
// 完整块贡献 k*k 的和,用平方和公式;尾块每天 n+1 枚
ll ans = n * (n + 1) * (2 * n + 1) / 6 + r * (n + 1);
printf("%lld\n", ans);
return 0;
}