题目大意
给你一个周期为 n n n 的无穷序列 a = ( a 1 , a 2 , a 3 , … ) a=(a _ 1,a _ 2,a _ 3,\dotsc) a=(a1,a2,a3,…) 的前 a a a 项 a 1 , a 2 , … , a N a _ 1,a _ 2,\dotsc,a _ N a1,a2,…,aN 。
请判断该无穷序列是否存在和为 s s s 的非空连续子序列。
题目做法
这道题目中的 s s s 并不是要直接建一个无穷序列暴力算出来,而是我们可以想到能装下一个循环的段落就可以不用考虑了,只需求出多余的序列的部分就行了。
求出多余的序列的部分又可以直接变成维护左右两个指针就可以了。如果区间和比目标值大,那就左指针加
1
1
1 。如果区间和比目标值小,那就右指针加
1
1
1 。如果相等就输出 Yes
就可以了。
AC代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,s,s1,s2,l,r,p,a[5000005];
main(){
cin>>n>>s;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i+n]=a[i]; //把数组复制一份到后面
s1+=a[i]; //计算一个周期的和
}
s2=s/s1; //有多少段周期
s=s-(s2*s1); //算出要算的
l=1;
r=1;
p=a[1];
while(l<=n&&r<=n*2){
if(p>s){
//如果区间和比目标值大,那就左指针加 1。
p-=a[l];
l++;
}else if(p<s){
//如果区间和比目标值小,那就右指针加 1。
r++;
p+=a[r];
}
if(p==s){
//找到相等的直接推出。
puts("Yes");
exit(0);
}
}
puts("No");
return 0;
}