[NOIP2004-提高] 津津的储蓄计划

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

逐月维护现金与存款两个状态:加 300 后不够预算即输出 -m,花完把整百转存,年末用整除结算 20% 利息。

OJ: roj

题目 ID: 3532

难度:入门

标签:入门模拟python

创建: 2026-10-02 05:51

更新: 2026-10-06 13:11

题目描述

津津每月月初拿到 300 元零花钱,按月预算花销,手中结余满整百就存到妈妈处,年末连本带 20% 利息返还,存款年末前不能取出。

输入格式: 12 行,每行一个小于 350 的非负整数,表示 1 月到 12 月的预算。 输出格式: 若某月钱不够用,输出第一个出问题的月份 −X-X;否则输出年末手中的总钱数。 样例 1: 预算 290 230 280 200 300 170 340 50 90 80 200 60,输出 -7。 样例 2: 将第 7 月预算改为 330,输出 1580。

思路

按月模拟:月初加 300,不够本月预算就输出 -m 并结束;花完后把结余的整百存入妈妈处(h/100*100,不足 100 自然为 0)。 12 个月都通过时输出年末总额:手中现金加存款及其 20% 利息,存款是 100 的倍数,利息用 s/5 精确计算。

参考代码

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 05:52
# update_at: 2026-10-02 05:52

import sys

MONTHLY_ALLOWANCE = 300  # 妈妈每月月初给的零花钱
DEPOSIT_LINE = 100       # 月末结余达到这个数才值得把整百存出去
BONUS_RATE = 5           # 年末利息 20% = 1/5,本金是 100 的倍数,整除即可


def solve() -> None:
    budgets = list(map(int, sys.stdin.buffer.read().split()))  # 1~12 月预算
    hand = 0    # 津津手中现金
    saved = 0   # 存在妈妈那里的本金(年末前取不出)

    for month, need in enumerate(budgets, 1):
        hand += MONTHLY_ALLOWANCE             # 月初先拿到零花钱
        if hand < need:                        # 手里的钱不够这个月的原定预算
            print(-month)                      # 输出第一个出问题的月份
            return
        hand -= need                           # 按预算花完,得到月末结余
        if hand >= DEPOSIT_LINE:               # 结余 ≥100,把整百存出去
            deposit = hand // 100 * 100
            hand -= deposit
            saved += deposit

    # 年末:妈妈还回本金 + 20% 利息,加上自己手里的现金
    print(hand + saved + saved // BONUS_RATE)


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 13:11
 * update_at: 2026-10-06 13:11
 */

#include <cstdio>

typedef long long ll;

const ll MONTHLY_ALLOWANCE = 300; // 妈妈每月月初给的零花钱
const ll DEPOSIT_LINE = 100;      // 月末结余达到这个数才把整百存出去
const ll BONUS_RATE = 5;          // 年末利息 20% = 1/5,本金是 100 的倍数,整除即可

ll budget[13]; // budget[m] 表示第 m 个月的预算

int main() {
    for (int m = 1; m <= 12; m++) {
        scanf("%lld", &budget[m]);
    }

    ll hand = 0;  // 津津手中现金
    ll saved = 0; // 存在妈妈那里的本金(年末前取不出)

    for (int m = 1; m <= 12; m++) {
        hand += MONTHLY_ALLOWANCE; // 月初先拿到零花钱
        if (hand < budget[m]) {    // 手里的钱不够这个月的原定预算
            printf("%d\n", -m);    // 输出第一个出问题的月份
            return 0;
        }
        hand -= budget[m]; // 按预算花完,得到月末结余

        ll deposit = hand / DEPOSIT_LINE * DEPOSIT_LINE; // 结余不足 100 时整除结果为 0,自动不存
        hand -= deposit;
        saved += deposit;
    }

    // 年末:妈妈还回本金加 20% 利息,再加上自己手里的现金
    printf("%lld\n", hand + saved + saved / BONUS_RATE);
    return 0;
}