http://acm.hdu.edu.cn/showproblem.php?pid=5183
2 1 1 1 2 1 -1 0
Case #1: Yes. Case #2: No.HintIf input is huge, fast IO method is recommended.
/** hdu 5183 hash 题目大意: NP?sum(i,j)=ai?ai+1+ai+2+?+(?1)j?iaj,求给定序列中是否有一个子序列得数为k 解题思路:题目数据很大,只能用O(n)的复杂度。看了杭电的解题报告后,很久才理解。我求将序列的后缀和表示出来(sum[0]-sum[1]+sum[2]-……) 然后从后往前枚举所求区间的第一个位置i,若为奇数那么在h1的哈希表中寻找是不是存在sum[i]-k,如果没有将sum[i]插入哈希表。 如果i为偶数那么在h2中寻找-sum[i]-k,将-sum[i]插入哈希表中。 由于哈希表的插入和查寻复杂度接近O(1),因此我们的算法复杂度总体为O(n) */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define LL long long const int MAXN=1000010; const int HASH=1000007; struct HASHMAP { int head[HASH],next[MAXN],ip; LL state[MAXN]; void init() { memset(head,-1,sizeof(head)); ip=0; } bool check(LL val) { int h=(val%HASH+HASH)%HASH; for(int i=head[h]; i!=-1; i=next[i]) if(state[i]==val)return true; return false; } int insert(LL val) { int h=(val%HASH+HASH)%HASH; for(int i=head[h]; i!=-1; i=next[i]) { if(val==state[i]) return 1; } state[ip]=val,next[ip]=head[h],head[h]=ip++; return 0; } } h1,h2; LL a[MAXN]; int n,k; int main() { int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(int i=0; i<n; i++) scanf("%I64d",&a[i]); bool flag=false; LL sum=0; h1.init(),h2.init(); h1.insert(0),h2.insert(0); for(int i=n-1; i>=0; i--) { if(flag==true)break; if(i&1) sum-=a[i]; else sum+=a[i]; if(i%2==0) { if(h1.check(sum-k)) flag=true; } else { if(h2.check(-sum-k)) flag=true; } h1.insert(sum); h2.insert(-sum); } printf("Case #%d: ",++tt); if(flag)printf("Yes.\n"); else printf("No.\n"); } return 0; }
原文:http://blog.csdn.net/lvshubao1314/article/details/44207259