FZU1465

题目链接:传送门

题目大意:给你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\n", 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\n",ans);
64     }
65     return 0;
66 }

 

           

posted @ 2016-05-30 15:03  Kurokey  阅读(154)  评论(0编辑  收藏  举报