金币

GitHub跳转原题关系图返回列表

第 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 枚,依此类推。给定天数 daysdays(1≤days≤100001\leq days\leq 10000),求累计金币数。

输入:一个整数 days。输出:累计金币数。

样例输入 6,输出 14。

思路

第 kk 块占 kk 天,前 nn 块共 n(n+1)2\frac{n(n+1)}{2} 天。先求不超过 days 的最大完整块编号 nn,再算完整块的平方和与尾块 r(n+1)r(n+1) 的贡献。

参考代码

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;
}