第一篇博客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 ",ans); 114 return 0; 115 }