音乐播放列表 C

文章描述了一个关于播放列表的问题,其中需要找出在给定时间后正在播放的歌曲及其开始播放的时间。最初的解决方案使用了for循环,但导致时间超限。随后通过改进,利用t/sum计算循环次数降低时间复杂度,最终给出优化后的C语言代码实现。
摘要由CSDN通过智能技术生成

【题目描述】

我们有一个播放列表 歌曲编号。歌曲持续几秒钟,输入中的所有值都是整数。N1,N2…,Ni.

播放播放列表时,歌曲将按此顺序播放。当歌曲结束时,播放列表会重复,再次从歌曲开始。播放歌曲时,下一首歌曲不播放;当一首歌曲结束时,下一首歌曲立即开始。

在播放列表开始播放后的几秒钟内,正在播放哪首歌曲?另外,自那首歌开始以来已经过去了多少秒?
没有输入播放列表在开始播放后更改歌曲。

满足:

1 ≤ N ≤ 10^{5}
1 ≤ T ≤ 10^{18}
1 ≤ A_{i} ≤ 10^{9}

【输入】

第一行两个整数 N 和 T,分别为歌曲的个数和听歌的时间(秒)。

第二行 N 个数字,为每首歌的时长。

【输出】

打印一个整数,表示播放列表开始播放后正好几秒钟正在播放的歌曲,以及一个整数,表示自该歌曲开始以来经过的秒数,用空格分隔。

样例输入

3 600
180 240 120

样例输出

1 60

样例输入

10 5678912340
1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

样例输出

6 678912340

解题思路

正常输入进去,然后把每首歌曲的时长存入数组 a[100005]。

这个题目最开始我是这样想的,一个循环把总时长减去每首歌曲的时长,若是总时长减完单首歌曲时长之后,接着对下一歌曲进行同样操作。当第 n 首歌曲减完之后,总时长还有剩余,就将 i=0;接着继续进入循环,直至总时长小于这首歌曲的时长,就结束。这样写的:

for(i=1;i<=n;i++)
{
	if(t-a[i]<=0)//如果总时长小于这首歌的时长了 
	{
		k=i;//记录下当前的的歌曲序号 
		break;//并结束循环 
	}
	t=t-a[i];//总时长减当前歌曲时长 
} 

但是这样写会时间超限,因为这个 for 循环可能会重复很多遍,得用更加简单的方法来实现。

所以我想到了 while 循环,输入每首歌曲时长时,就把歌曲列表的总时长求出来,然后放在将 t-sum>0 当做循环继续的条件,这样时间复杂度就低了很多。这样写的:

while(t-sum>0)//循环继续的条件,总时长不能为负数 
{
	t=t-sum;
} 

接着还是不对,时间超限了,还得找其他简单的方法,毕竟在极端条件下:五首歌曲,每首歌曲两秒钟,但是总时长为10^{18},这样用了 while 循环,while应该循环10^{17}次,时间复杂度还是很高。然后我想到了一种很快的方法,就是用 t/sum,这时如果这个值大于零,或者说这个值很大,大到上面所说的10^{17},那我可以一步解决掉 while 循环的内容,像这样:

cha=t/sum;
t=t-cha*sum;

 那么现在可以把时间超限的问题解决了;

代码如下:

#include<stdio.h>
long long a[100005];//存放每首歌曲的时长 
int main()
{
	long long n,i,t;
	long long k,sum=0;//k记录最后到达的歌曲编号,sum为播放列表的所有歌曲时长 
	scanf("%lld %lld",&n,&t);
	for(i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);//输入 
		sum=sum+a[i];//统计列表歌曲的时长 
	}
	long long cha=t/sum;//找总时长 t是列表歌曲时长的多少倍 
	t=t-cha*sum;//总时长减去倍数与列表歌曲时长的积,相当于歌单被循环播放了 cha遍 
	for(i=1;i<=n;i++)
	{
		if(t-a[i]<=0)//如果现在的总时长小于等于当前的歌曲时长就结束循环 
		{
			k=i;//记录当前歌曲编号 
			break;
		}
		t=t-a[i];//总时长减当前歌曲时长 
	}
	printf("%lld %lld\n",k,t);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明里灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值