第一篇博客emmm
根据kuangbin dalao的poj刷题指南做的
一道不是很简单的哈希题目
题意是求特征之和相同的第i头牛到第j头牛的max(j-i)
一开始是没有思路的,苦思冥想半天
然后(看了题解以后)手推公式:
num[i][1]+...+num[j][1]=num[i][2]+....+num[j][2]=num[i][k]+...+num[j][k];
①num[i][1]+...+num[j][1]=num[i][k]+...+num[j][k];
②sum[i][k]=sum[i-1][k]+num[i][k];
①,②=>sum[j][k]-sum[i][k]=sum[j][0]-sum[i][0];
=>sum[j][k]-sum[j][0]=sum[i][k]-sum[i][0];
所以对于sum矩阵,每个元素减去第一列
然后求sum矩阵相同的行的最大距离即可
二进制转化成k进制作为哈希值。
自己踩的坑如下:
(1)mod余数越界,调了好久
(2)矩阵每列元素减去第一列元素会导致最后的hash值可能是负的,要用abs把它变成正数
(3)search的时候不要找到就直接返回j值,要找到最后一个满足cmp的j值,因为前向星是倒着存的,而我们要的是最靠前的j值,越靠前,对于当前i值来说,距离越大,所以最晚出现的值是符合条件的
(4)脑残错误:
for(int i=1;i<=n;i++)
71 {
73 for(int j=1;j<=k;j++)
74 { 75 num[i][j]-=num[i][1];//天真地以为这样就减去第一列了,当j=1执行后,num[i][1]已经 等于0了。。。还傻fufu调了半天(逃。。。。) 77 } 78 }
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 const int mod=1000007;
8 const int maxn=1000009;
9 int n,k,cnt;
10 int num[1000100][31],head[1000100];
11 struct node
12 {
13 int num[31];
14 int next;
15 int p;
16 }edge[maxn];
17 void ins(int *num,int h,int p)
18 {
19 for(int i=1;i<=30;i++)
20 edge[cnt].num[i]=num[i];
21 edge[cnt].p=p;
22 edge[cnt].next=head[h];
23 head[h]=cnt++;
24 }
25 bool cmp(int *num1,int *num2)
26 {
27 for(int i=1;i<=k;i++)
28 if(num1[i]!=num2[i]) return 0;
29 return 1;
30 }
31 int search(int *num,int h)
32 {
33 int flag=0,ans=0;
34 for(int i=head[h];i!=-1;i=edge[i].next)
35 {
36 if(cmp(num,edge[i].num))
37 {
38 ans=edge[i].p; //这里,不要马上返回
39 }
40 //return edge[i].p;
41 }
42 return ans;
43 }
44 int main()
45 {
46 int flag=0;
47 memset(head,-1,sizeof(head));
48 scanf("%d%d",&n,&k);
49 for(int i=1;i<=n;i++)
50 {
51 int x;
52 scanf("%d",&x);
53 for(int j=1;j<=k;j++)
54 {
55 num[i][j]=x%2;
56 x/=2;
57 }
58 }
59 for(int i=2;i<=n;i++)
60 {
61 for(int j=1;j<=k;j++)
62 num[i][j]+=num[i-1][j];
63 }
64 /*for(int i=1;i<=n;i++)
65 {
66 for(int j=1;j<=k;j++)cout<<num[i][j];
67 cout<<endl;
68 }*/
69 int ans=0;
70 for(int i=1;i<=n;i++)
71 {
72 int t=num[i][k];
73 for(int j=1;j<=k;j++)
74 {
75 num[i][j]-=t;
76 //if(num[i][j]<0) num[i][j]=-num[i][j];
77 }
78 }
79 /*for(int i=1;i<=n;i++)
80 {
81
82 for(int j=1;j<=k;j++)
83 cout<<num[i][j];
84 cout<<endl;
85 }*/
86 for(int i=1;i<=n;i++)
87 {
88 int base=0;
89 for(int j=1;j<=k;j++)
90 {
91 base+=num[i][j];
92 base*=10;
93 base%=mod;
94 //cout<<base<<endl;
95 }
96 if(base<0) base=-base;
97 int tmp=search(num[i],base);
98 if(tmp>0)
99 {
100 int t=abs(tmp-i);
101 if(t>ans)
102 {
103 //cout<<tmp<<" "<<i<<endl;
104 ans=t;
105 }
106 }
107 if(base==0)
108 {
109 ans=max(i,ans);
110 }
111 ins(num[i],base,i);
112 }
113 printf("%d\n",ans);
114 return 0;
115 }