题目链接:传送门
题目大意:给你n个整数(可正可负),求有多少个连续的子序列的和==m(时限1S)
题目思路:前缀和+手写hash(map效率太慢,会超时)
具体做法是用一个数组sum,数组的第i位保存前1~i个数的和,那么从第x个元素到到第y个元素的和就可以表示为sum[y]-sum[x]
现在我们要求有多少个连续子序列的和==m,也就是找出有多少个sum[y]-sum[x]==m。
如果给你的数都是正整数就好办了,不难想到可以用尺取法(双指针扫描),但是难点在于有负数,也就是sum数组的值很杂乱。
但其实,我们观察一下式子 sum[y]-sum[x]==m,如果把它转换一下 sum[y]-m=sum[x]。那么我们对于sum[i],只需要找到
在i之前出现了多少sum[i]-m,答案就加上sum[i]-m的个数,所以我们只需从头扫一遍即可。复杂度O(n),但是map效率太慢,所以还需
手写hash
MAP超时代码
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #include <vector> 6 #include <string> 7 #include <stack> 8 #include <cmath> 9 #include <cstdlib> 10 #include <iostream> 11 #include <map> 12 using namespace std; 13 const int INF = 0x3f3f3f3f; 14 typedef long long ll; 15 const int mod = 1234577; 16 const int N = 1e6 + 1000; 17 map<ll, int> mp; 18 19 ll sum[N]; 20 int main() { 21 int n, m, v; 22 int group; scanf("%d", &group); 23 while(group--) { 24 scanf("%d%d", &n, &m); 25 sum[0] = 0; 26 for(int i = 1; i <= n; ++i) { 27 scanf("%d", &v); 28 sum[i] = sum[i - 1] + v; 29 } 30 int ans = 0; 31 mp.clear(); mp[0] = 1; 32 for(int i = 1; i <= n; ++i) { 33 ll s = sum[i] - m; 34 int num = mp[s]; 35 ans += num; 36 37 mp[sum[i]]++; 38 } 39 printf("%d ", ans); 40 } 41 return 0; 42 }
AC代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #define mst(x,y) memset(x,y,sizeof(x)) 8 using namespace std; 9 const long long MOD=(1ll<<50); 10 const long long MMM=1234567; 11 const int N=1000005; 12 13 int n,m; 14 long long key[N],sum[N]; 15 int head[MMM],cnt[N],next[N],hcnt; 16 struct Myhas{ 17 void init(){ 18 mst(head,-1); 19 mst(cnt,0); 20 hcnt=0; 21 } 22 void ins(long long x){ 23 int h=x%MMM; 24 key[hcnt]=x; 25 cnt[hcnt]=1; 26 next[hcnt]=head[h]; 27 head[h]=hcnt++; 28 } 29 void add(long long x){ 30 int h=x%MMM; 31 for(int i=head[h];~i;i=next[i]){ 32 if(key[i]==x){++cnt[i];return;} 33 } 34 } 35 int query(long long x){ 36 int h=x%MMM; 37 for(int i=head[h];~i;i=next[i]){ 38 if(key[i]==x) return cnt[i]; 39 } 40 return -1; 41 } 42 }has; 43 int main(){ 44 int i,j,group,x,ans; 45 scanf("%d",&group); 46 while(group--){ 47 scanf("%d%d",&n,&m); 48 for(i=1;i<=n;++i){ 49 scanf("%d",&x); 50 sum[i]=sum[i-1]+x; 51 } 52 ans=0; 53 has.init(); 54 has.ins(MOD); 55 for(i=1;i<=n;++i){ 56 long long xx=sum[i]-m+MOD; 57 int num=has.query(xx); 58 if(num!=-1)ans+=num; 59 xx=(sum[i]+MOD); 60 if(has.query(xx)!=-1)has.add(xx); 61 else has.ins(xx); 62 } 63 printf("%d ",ans); 64 } 65 return 0; 66 }