#P3358. 第1题-落叶数量
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 105
            Accepted: 34
            Difficulty: 2
            
          
          
          
                       所属公司 : 
                              科大讯飞
                                
            
                        
              时间 :2025年8月9日
                              
                      
          
 
- 
                        算法标签>模拟          
 
第1题-落叶数量
思路
将一年 12 个月的“掉落量”形成固定模式:
- 
非刮风月掉
m,刮风月掉2m。 - 
一年总掉落量:
Y=(12−q)⋅m+q⋅(2m) = (12+q)⋅m
 
做法:
- 
先整年跳跃:设可完整经过的年数
k=⌊Yn−1⌋
跳过
k年(12k个月),剩余n ← n - kY。用
(n-1)//Y可以避免“正好整年结束”的边界误差,同时不影响最优性。 - 
对下一年只需在 最多 12 个月 内顺序扫一遍,用前缀和(或简单累加)找到第一个使累计掉落 ≥ 剩余
n的月份。 
算法步骤
- 构造数组 
drop[1..12]:普通月为m,[p, p+q-1]为2m。 - 计算 
Y = sum(drop);k=(n-1)//Y;ans_month = 12*k;rem = n - k*Y。 - 从 1 月到 12 月累加 
drop[i],首次使累计 ≥rem时,ans_month += i即为答案。 
复杂度分析
- 时间:
O(12)(整年跳过后只需扫一年的 12 个月)。 - 空间:
O(1)。 
代码
Python
# 读取 n, m, p, q,计算最少月份数
import sys
def solve():
    data = sys.stdin.read().strip().split()
    if not data:
        return
    n, m, p, q = map(int, data[:4])
    # 构造一年 12 个月的掉落量
    drop = [m] * 12
    for i in range(p - 1, p - 1 + q):
        drop[i] = 2 * m
    yearly = sum(drop)                  # Y = (12 + q) * m
    years = (n - 1) // yearly           # 可整年跳过的年数
    months = years * 12
    rem = n - years * yearly            # 跳过后剩余的叶子数
    # 在下一年内顺序找首个前缀和 >= rem 的月份
    acc = 0
    for i in range(12):
        acc += drop[i]
        months += 1
        if acc >= rem:
            print(months)
            return
if __name__ == "__main__":
    solve()
Java
// 计算最少月份数:前缀和 + 整年跳跃
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        if (!sc.hasNextLong()) return;
        long n = sc.nextLong();   // 初始叶子数
        long m = sc.nextLong();   // 普通月每月掉落
        int p = sc.nextInt();     // 刮风期起始月(1..12)
        int q = sc.nextInt();     // 刮风期持续月数
        long[] drop = new long[12];
        Arrays.fill(drop, m);
        for (int i = p - 1; i < p - 1 + q; i++) drop[i] = 2 * m;
        long yearly = 0;
        for (long x : drop) yearly += x;     // 一年总掉落量
        long years = (n - 1) / yearly;       // 整年跳过
        long months = years * 12;
        long rem = n - years * yearly;       // 剩余叶子
        long acc = 0;
        for (int i = 0; i < 12; i++) {
            acc += drop[i];
            months++;
            if (acc >= rem) {
                System.out.println(months);
                return;
            }
        }
    }
}
C++
// 计算最少月份数:前缀和 + 整年跳跃
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    long long n, m;
    int p, q;
    if (!(cin >> n >> m >> p >> q)) return 0;
    vector<long long> drop(12, m);         // 一年 12 个月的掉落量
    for (int i = p - 1; i < p - 1 + q; ++i) drop[i] = 2 * m;
    long long yearly = 0;
    for (auto x : drop) yearly += x;       // 一年总掉落
    long long years = (n - 1) / yearly;    // 可整年跳过的年数
    long long months = years * 12;
    long long rem = n - years * yearly;    // 剩余
    long long acc = 0;
    for (int i = 0; i < 12; ++i) {
        acc += drop[i];
        ++months;
        if (acc >= rem) {
            cout << months;
            return 0;
        }
    }
    return 0;
}
        题目内容
牛牛望着窗外的树叶发出疑问:这棵老树什么时候才能掉完所有的叶子?
1.在一月初,树上有n片叶子;
2.每月会掉落m片叶子;
3.每年从p月开始会有q个月的刮风期;
4.刮风期每月会掉落2×m片叶子。
当叶子数不大于零时,视为所有叶子已掉落。现在请你编写一个程序,帮助牛牛计算:落下所有叶子需要几个月。
输入描述
在一行上输入四个整数,依次为:
- n(1≦n≦106),表示树上的叶子数;
 - m(1≦m≦n),表示每月会掉落的叶子数;
 - p(1≦p≦12),表示从几月开始刮风;
 - q(1≦q≦13−p),表示刮风期持续的月份数,保证刮风期不会持续多年。
 
输出描述
输出一个整数,表示使叶子全部掉落所需的月数。
样例1
输入
10 1 1 3
输出
7
说明
在这个样例中:
- 一月为刮风期,掉落2片,剩余8片;
 - 二月为刮风期,掉落2片,剩余6片;
 - 三月为刮风期,掉落2片,剩余4片;
 - 四月为常规期,掉落1片,剩余3片;
 - 五月为常规期,掉落1片,剩余2片;
 - 六月为常规期,掉落1片,剩余1片;
 - 七月为常规期,掉落1片,剩余0片;
 
因此总共需要3+4=7个月。
样例2
输入
50 10 4 4
输出
4
说明
在这个样例中:
- 
一月、二月、三月每个月落10片;
 - 
四月、五月、六月、七月为刮风期,每月落20片;
 
因此,所有的叶子都会在第4个月落下。
样例3
输入
100 2 5 8
输出
31
说明
每年的五月至十二月为八个月的刮风期。