Gold Balanced Lineup--POJ 3274
1、题目类型:哈希表、位运算。
2、解题思路:题意,N个数,它们用K位的二进制表示,寻找最长的区间使其各个进制位上的和都没有发生变化的情况。步骤,(1)将所有N个数转化为K位的二进制形式,并比较与初始位置的差值存储在arr[i]中;(2)Hash编码arr[i],Hash编码公式为:tmp=((tmp<<2)+(v[i]>>4))^(v[i]<<10) ;(3)判断是否存在冲突,存在冲突并且匹配成功时,判断区间大小,直到找到答案。
3、注意事项:注意当Hash编码冲突且匹配不成功时,tmp++,下一位保存;注意取prime的大小要求适当。
4、实现方法:
1 #include<iostream>
2 using namespace std;
3 #define maxn 100010
4 #define prime 999983
5
6 int n,k,ans;
7 int arr[maxn][31],sum[maxn][31],hash[1000000];
8
9 //Hash编码方式
10 int Encode(int *v,int k)
11 {
12 int i,tmp=0;
13 //Hash公式
14 for(i=0;i<k;i++)
15 tmp=((tmp<<2)+(v[i]>>4))^(v[i]<<10);
16 tmp = tmp%prime;
17 if(tmp<0) tmp=tmp+prime;
18 return tmp;
19 }
20
21 int main()
22 {
23 int i,j,num,tmp;
24 memset(sum,0,sizeof(sum));
25 memset(hash,-1,sizeof(hash));
26 memset(arr,0,sizeof(arr));
27
28 scanf("%d%d",&n,&k);
29 hash[Encode(arr[0],k)]=0;
30
31 for(i=1;i<=n;i++)
32 {
33 scanf("%d",&num);
34 for(j=0;j<k;j++)
35 {
36 arr[i][j]=num%2;
37 num>>=1;
38 sum[i][j]=sum[i-1][j]+arr[i][j];
39 arr[i][j]=sum[i][j]-sum[i][0];
40 }
41 tmp=Encode(arr[i],k);
42 //Hash存在冲突
43 while(hash[tmp]!=-1)
44 {
45 //验证arr[i]是否相同
46 for(j=1;j<k;j++)
47 {
48 if(arr[i][j]!=arr[hash[tmp]][j])
49 break;
50 }
51 if(j==k)
52 {
53 if(i-hash[tmp]>ans)
54 ans=i-hash[tmp];
55 break;
56 }
57 tmp++;
58 }
59 //Hash不存在冲突
60 if(hash[tmp]==-1)
61 hash[tmp]=i;
62 }
63 printf("%d\n",ans);
64 return 0;
65 }