poj3274

很不错的hash

优化有两个方面:1.根据题目换一个更优化的算法 2.在算法运行过程中优化

这题除了暴力好像没别的办法了吧?

但是暴力也是有策略的!

到第i只牛特征为j的总数为sum[i,j];

找到最大的区间(l,r]使得sum[r,1]-sum[l,1]=sum[r,2]-sum[l,2]…=sum[r,k]-sum[l,k]

整理就得sum[r,1]-sum[r,2]=sum[l,1]-sum[l,2] sum[r,1]-sum[r,3]=sum[r,1]-sum[r,3]……

于是做到每只牛的时候,我们就能得到一个序列。满足条件就是两个序列相等,

怎么快速判断序列:hash!得解!

 1 type link=^node;
 2      node=record
 3        data:longint;
 4        next:link;
 5      end;
 6 const key=200007;
 7 var hash:array[0..200010] of link;
 8     sum:array[0..40] of longint;
 9     num:array[0..100010,0..40] of longint;
10     ans,n,k,x,j,i,s:longint;
11 function max(a,b:longint):longint;
12   begin
13     if a>b then exit(a) else exit(b);
14   end;
15 
16 function allsame(x,y:longint):boolean;  //注意可能出现hash值相同但序列不同
17   var i:longint;
18   begin
19     allsame:=true;
20     for i:=1 to k do
21       if num[x,i]<>num[y,i] then exit(false);
22   end;
23 
24 procedure add(x,y:longint);
25   var p:link;
26   begin
27     new(p);
28     p^.data:=y;
29     p^.next:=hash[x];
30     hash[x]:=p;
31   end;
32 
33 procedure push(x,i:longint);
34   var p:link;
35   begin
36     if hash[x]=nil then add(x,i)
37     else begin
38       p:=hash[x];
39       while p<>nil do
40       begin
41         if allsame(p^.data,i) then
42         begin
43           ans:=max(ans,i-p^.data);  //如果相同,那么当前序列就无需入hash
44           exit;
45         end;
46         p:=p^.next;
47       end;
48       add(x,i);  //拉链法解决冲突
49     end;
50   end;
51 
52 begin
53   readln(n,k);
54   add(0,0);
55   for i:=1 to n do
56   begin
57     readln(x);
58     j:=0;
59     while x<>0 do
60     begin
61       j:=j+1;
62       sum[j]:=sum[j]+x mod 2;
63       x:=x shr 1;
64     end;
65     s:=0;
66     for j:=1 to k do
67     begin
68       num[i,j]:=sum[1]-sum[j];   //生成序列
69       s:=(s+sqr(num[i,j])*j mod key) mod key ; //很奇怪的hash……
70     end;
71     push(s,i);  //hash值都不同那么序列一定不同
72   end;
73   writeln(ans);
74 end.
View Code

判断两个序列是否相同,hash是个好方法!

原文地址:https://www.cnblogs.com/phile/p/4473286.html