poj3274Gold Balanced Lineup

http://poj.org/problem?id=3274

网上题解

数组sum[i][j]表示从第1到第i头cow属性j的出现次数。

所以题目要求等价为:

求满足

sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i)

中最大的i-j

 

将上式变换可得到

sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0]

sum[i][2]-sum[i][0] = sum[j][2]-sum[j][0]

......

sum[i][k-1]-sum[i][0] = sum[j][k-1]-sum[j][0]

 

令C[i][y]=sum[i][y]-sum[i][0] (0<y<k)

初始条件C[0][0~k-1]=0

 

所以只需求满足C[i][]==C[j][] 中最大的i-j,其中0<=j<i<=n。

C[i][]==C[j][] 即二维数组C[][]第i行与第j行对应列的值相等,

那么原题就转化为求C数组中 相等且相隔最远的两行的距离i-j

View Code
 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 #define size 200010
 8 #define MOD 97777
 9 int sum[100010][31],c[100010][31],t,head[size+10],next[size+10],v[size+10];
10 void init()
11 {
12     t = 0;
13     memset(head,-1,sizeof(head));
14 }
15 void add(int a,int b)
16 {
17     next[t] = head[a];
18     head[a] = t;
19     v[t] = b;
20     t++;
21 }
22 int main()
23 {
24     int i,j,k,n,g,x,bi[31];
25     while(cin>>n>>k)
26     {
27         init();
28         memset(sum,0,sizeof(sum));
29         memset(c,0,sizeof(c));
30         for(i = 1; i <= n ; i++)
31         {
32             cin>>x;
33             g = 0;
34             while(x)
35             {
36                 g++;
37                 j = x%2;
38                 sum[i][g]=j;
39                 x = x/2;
40             }
41             for(j = 1 ; j <= k  ; j++)
42             sum[i][j]+=sum[i-1][j];
43         }
44         int mi = 0;
45         for(i = 1; i <= n ; i++)
46         {
47             int s = 0;
48             for(j = 2 ; j <= k ;j++)
49             {
50                 c[i][j] = sum[i][j]-sum[i][1];
51                 s = c[i][j]*j;//哈希
52             }
53             for(j = 2 ; j <= k ;j++)
54                 if(c[i][j]!=0)  break;
55             if(j==k+1&&mi<i) mi = i;
56             s = s%MOD;
57             if(s<0) s+=MOD;
58             int flag = 0,a;
59             for(j = head[s] ; j!=-1 ; j = next[j])//解决冲突
60             {
61                 flag = 1;
62                 for(a = 2 ; a <= k  ; a++)
63                 {
64                     if(c[i][a]!=c[v[j]][a])
65                     {
66                         flag = 0;
67                         break;
68                     }
69                 }
70                 if(flag&&mi<i-v[j])
71                 mi = i-v[j];
72             }
73             add(s,i);
74         }
75         cout<<mi<<endl;
76     }
77     return 0;
78 }
原文地址:https://www.cnblogs.com/shangyu/p/2871289.html