记sum=a[1]+a[2]+a[3]+...+a[n]。
该序列以a[1],a[2],a[3]....a[n]为循环节,明显的,问题可转化为:s%sum是否为该序列的某个连续子序列和。
断环为链。将a复制一份。
枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O(logn),哈希O(1)均可以实现查找。
以a[i+1]为左端点的所有区间再从头求一遍?
不行的。
在处理a[i]时,每个区间减去a[i]即是a[i+1]的情况。
这里,在查找s的时候加上要减去的值就可以巧妙地实现了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
unordered_map<int,bool>mp;signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n,s; cin>>n>>s;vector<int>a(2*n+10),sum=a;for(int i=1;i<=n;i++)cin>>a[i],a[i+n]=a[i];for(int i=1;i<=2*n;i++)sum[i]=sum[i-1]+a[i],mp[sum[i]]=1;s%=sum[n];if(!s){cout<<"Yes"; return 0;}for(int i=0;i<n;i++){if(mp[s+sum[i-1]]){cout<<"Yes"; return 0;}}cout<<"No";
}
对比总结:
map,优点:有序;缺点:增、删、改、查时间O(logn)。
unordered_map,优点:增、删、改、查O(1);缺点:无序。
25/2/21