1 条题解

  • 0
    @ 2026-6-19 10:30:20

    📝 题目大意

    有一个包含 NN 首歌的循环播放列表,每首歌有其固定的时长 AiA_i 秒。给定一个时间点 TT(保证不会恰好落在歌曲切换的瞬间),求此时正在播放哪首歌,以及这首歌已经播放了多少秒。

    💡 解题思路

    1. 题目分析:播放列表是周期循环的,总周期为 S=i=1NAiS = \sum_{i=1}^{N} A_i。由于 N105N \le 10^5T1018T \le 10^{18}Ai109A_i \le 10^9,需要开 long long,且不能直接模拟 TT 秒的播放过程。

    2. 算法推导

      • 先算出所有歌曲的总时长 SS
      • TTSS 取模:TTmodST \gets T \bmod S。这一步将 TT 映射到第一个播放周期内,因为每经过一个完整周期,播放状态会回到起点。
      • 遍历歌曲 1N1 \sim N
        • T<AiT < A_i,说明当前时间点落在这首歌的播放过程中,输出歌曲编号 ii 和已播放时间 TT
        • 否则,TTAiT \gets T - A_i,表示这首歌已经完整播完,跳过它继续检查下一首。
    3. 边界与细节

      • 题目保证 TT 不会恰好落在歌曲切换时刻,因此不会出现 T=0T = 0T=AiT = A_i(取模后)的边界情况,代码中直接用 < 判断即可。
      • TT 很大时(101810^{18} 级别),SS 可能达到 101410^{14},需要使用 long long(C++ 中 int64_t#define int long long)。
      • 取模操作 TmodST \bmod S 保证了后续遍历时 T<ST < S,因此一定能在 NN 首歌中找到答案,不会出现遍历完未输出的情况。

    ⏱️ 复杂度分析

    • 时间复杂度O(N)O(N),一次求和与一次遍历。
    • 空间复杂度O(N)O(N),用于存储 NN 首歌的时长数组。

    💻 标准代码 (C++)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long          // 数据范围较大,统一使用 long long
    const int N=1e5+10;
    int s,a[N];                    // s: 所有歌曲总时长, a[i]: 第 i 首歌的时长
    signed main()
    {
    	int n,t;scanf("%lld%lld",&n,&t);
    	for(int i=1;i<=n;i++)scanf("%lld",&a[i]),s+=a[i]; // 读入每首歌并累加总时长
    	t=t%s;                     // 取模,将 T 映射到第一个播放周期内
    	for(int i=1;i<=n;i++)
    	{
    		if(t<a[i])             // 当前时间落在第 i 首歌的播放过程中
    		{
    			printf("%lld %lld\n",i,t); // 输出歌曲编号和已播放秒数
    			return 0;
    		}
    		else t-=a[i];          // 跳过这首歌,减去其时长
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    659
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    3
    已通过
    3
    上传者