[NOIP2002-普及]级数求和

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

利用调和级数严格递增且发散,从 1 开始逐项累加 1/n,部分和第一次超过 K 时的 n 即为答案,最大 K=15 也只需约 3×10^6 次加法。

OJ: roj

题目 ID: 3512

难度:入门

标签:模拟数学入门

创建: 2026-10-02 04:40

更新: 2026-10-06 12:31

题目描述

已知 Sn=1+12+13+⋯+1nS_n = 1 + \frac12 + \frac13 + \dots + \frac1n。给定整数 KK(1≤K≤151 \le K \le 15),求最小的正整数 nn 使得 Sn>KS_n > K。

输入格式:一个正整数 KK
输出格式:一个正整数 nn

样例输入:1
样例输出:2

思路

调和级数严格递增且发散,直接从 n=1n=1 开始逐项累加 1n\frac1n,维护部分和 ss,当 s>Ks > K 时当前的 nn 即为答案。K≤15K \le 15 时答案不超过约 3.3×1063.3 \times 10^6,直接模拟即可通过。

参考代码

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-10-02 04:40
# update_at: 2026-10-02 04:40

import sys


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    k = next(data)  # 输入只有一个整数 K

    s = 0.0  # S_n = 1 + 1/2 + ... + 1/n,严格递增
    n = 0
    while s <= k:  # 边加边判:S_n 一旦超过 K 就停
        n += 1
        s += 1.0 / n

    print(n)


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-06 12:31
 * update_at: 2026-10-06 12:31
 */

#include <iostream>
using namespace std;

typedef long long ll;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int k;
    cin >> k;

    double s = 0.0; // 当前调和级数部分和 S_n
    int n = 0;      // 当前项数
    while (s <= k) { // 严格大于 K 时停止
        ++n;
        s += 1.0 / n;
    }

    cout << n << "\n";
    return 0;
}