题目链接:Gold Balanced Lineup
解题思路:这道题看了解题报告之后才做出来,先将每一位的1或0累加起来做一个sum[i][j],表示第i头牛的j属性累加到现在的和。那么如果在这个区间里面每种属性出现的次数相同的话就表明sum[i][k] - sum[j][k] = sum[i][1] - sum[j][1]变形一下就得到 sum[i][k] - sum[i][1] = sum[j][k] - sum[j][1]那么k位就可以生成k - 1个数组成的‘特征’序列,只要这两个序列相等那么算一下下标差,取最大值就好了。容易错的地方就是边界问题如这组数据4 4 1 2 4 8,应该为4,所以要在之前插入一个0牛,所有数据都是0。还有就是如果只有1头牛就能满足所有属性出现一次,而且其他的答案均不满足,这时是1不是0。
PS:个人感觉hash的题目就是最终还是在众多数据里面找到两个或者多个相同的数据,数据形式可能是多样的。但是每一个hash的问题到最后都会简化成这个基础问题。难点就只是前面的问题简化是否可以想得出来。再者就是计算HASH值得时候,好方法很多,对于时间复杂度影响很大,还需好好学习。
#include<stdio.h>
#include<vector>
#include<stdlib.h>
#include<string.h>
#define MAX 100000
#define FI 99991
using namespace std;
struct A{
int num[32];
};
typedef struct A node;
vector<node> cow[MAX];
int sum[32];
int main(){
int i, j, k, n, tem, hash, ans, tot, key;
node s;
//freopen("in.txt", "r", stdin);
while(scanf("%d%d", &n, &k) != EOF){
ans = 0;
key = 0;
for(i = 0; i < MAX; i++){
cow[i].clear();
}
memset(sum, 0, sizeof(sum));
memset(s.num, 0, sizeof(s.num));
cow[0].push_back(s);
for(i = 1; i <= n; i++){
scanf("%d", &tem);
tot = hash = 0;
for(j = 0; j < k; j++){
tem >>= j == 0 ? j : 1;
if(tem & 1){
sum[j]++;
tot++;
}
if(tot == k) key = 1;
if(j > 0){
s.num[j] = sum[j] - sum[0];
hash += s.num[j] * j;
}
}
s.num[0] = i;
hash = abs(hash) % FI;
for(j = 0; j < cow[hash].size(); j++){
int flag = 1;
for(int g = 1; g < k; g++){
if(cow[hash][j].num[g] != s.num[g]){
flag = 0;
break;
}
}
if(flag){
ans = (s.num[0] - cow[hash][j].num[0]) > ans ? s.num[0] - cow[hash][j].num[0] : ans;
}
}
cow[hash].push_back(s);
}
if(ans)
printf("%d\n", ans);
else
printf("%d\n", key);
}
return 0;
}