IT民工
加油!

 

这个题看了题解之后才会写的,每头牛最多有k个属性,用给出数字的对应二进制位表示,

0为没有这种属性,1为具有这种属性。要求的是最长的一个牛的序列,使得每种属性出现

的次数相同。参考网上的hash函数  ret = ((ret << 2) + (a[i] >> 4)) ^ (a[i] << 10); 

用sum[i][j]表示前i头牛的第j种属性出现的次数。用c[i][j]存储sum[i][j] - sum[i][0]的

值,代表前i头牛第j种属性出现次数与第0种属性出现次数的差值。如果存在i1和i2,使得

c[i1][j] = c[i2][j]   0< j < k, i1到i2这一段就是符合要求的一个解。找到最长的i2 - i1

就是答案。这里理解过来就是在i1到i2所有属性出现次数的增量都相同。

 

[分析]:以样例为例:

转换成二进制

111

110

111

010

001

100

010

sum[i][j]的值,累加的过程。

111    

221    

332     

342    

343

443

453

 

都减去第0种属性出现的次数和

000

110 i1

110

120

010

110 i2

120

到此可以看出规律, i2 - i1就是所求答案。

 

/*Accepted    26420 KB    266 ms    C++    1471 B    2012-08-24 14:41:44*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

const int MAXN = 100100;
const int MAXK = 32;

int sum[MAXN][MAXK], c[MAXN][MAXK];
int first[MAXN], next[MAXN], v[MAXN], e;
int n, p, ans;

void addedge(int x, int y)
{
    next[e] = first[x], v[e] = y;
    first[x] = e ++;
}

int hash(int c[])
{
    int ret = 0, i;
    for(i = 0; i < p; i ++)
        ret = ((ret << 2) + (c[i] >> 4)) ^ (c[i] << 10);
    ret = (ret % MAXN + MAXN) % MAXN;
    return ret;
}

void cal()
{
    int i, j, k, a, h;
    memset(sum, 0, sizeof sum);
    memset(c, 0, sizeof c);
    memset(first, -1, sizeof first);
    e = ans = 0;
    addedge(hash(c[0]), 0);
    for(i = 1; i <= n; i ++)
    {
        scanf("%d", &a);
        for(j = 0; j < p; j ++)
        {
            sum[i][j] = sum[i - 1][j] + (1 & a);
            a >>= 1;
        }
        for(j = 0; j < p; j ++)
        {
            c[i][j] = sum[i][j] - sum[i][0];
        }
        h = hash(c[i]);
        for(j = first[h]; j != -1; j = next[j])
        {
            bool ok = true;
            for(k = 0; k < p; k ++)
            {
                if(c[v[j]][k] != c[i][k])
                {
                    ok = false;
                    break;
                }
            }
            if(ok && ans < i - v[j])
                ans = i - v[j];

        }
        addedge(h, i);
    }
}

int main()
{
    while(scanf("%d%d", &n, &p) != EOF)
    {
        cal();
        printf("%d\n", ans);
    }
    return 0;
}

 

 

 

posted on 2012-08-24 15:27  找回失去的  阅读(156)  评论(0编辑  收藏  举报