【题目描述】
我们有一个播放列表 歌曲编号。歌曲持续几秒钟,输入中的所有值都是整数。N1,N2…,Ni.
播放播放列表时,歌曲将按此顺序播放。当歌曲结束时,播放列表会重复,再次从歌曲开始。播放歌曲时,下一首歌曲不播放;当一首歌曲结束时,下一首歌曲立即开始。
在播放列表开始播放后的几秒钟内,正在播放哪首歌曲?另外,自那首歌开始以来已经过去了多少秒?
没有输入播放列表在开始播放后更改歌曲。
满足:
1 ≤ N ≤
1 ≤ T ≤
1 ≤ ≤
【输入】
第一行两个整数 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;
}
接着还是不对,时间超限了,还得找其他简单的方法,毕竟在极端条件下:五首歌曲,每首歌曲两秒钟,但是总时长为,这样用了 while 循环,while应该循环次,时间复杂度还是很高。然后我想到了一种很快的方法,就是用 t/sum,这时如果这个值大于零,或者说这个值很大,大到上面所说的,那我可以一步解决掉 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;
}