luoguP2843 暗杀

luoguP2843 暗杀

Description

给定N个K位的二进制数,找到最长的一段使得每位上的1的个数相同

Solution

快速计算同一位一段上的1的个数可以直接前缀和实现,令 $ sum_{k,i} $ 表示考虑第k位到第i个数的前缀和

考虑只有两位的二进制数,当满足条件时有

$ sum_{1,i}  - sum_{1,j} $ = $ sum_{2,i} - sum_{2,j}$

移项得 $ sum_{2,i} - sum_{1,i} $ = $ sum_{2,j} - sum_{1,j} $

于是如果一段数符合要求,则满足任意一位上都有 $ sum_{k,i} - sum_{1,i} $ = $ sum_{k,j} - sum_{1,j} $

于是考虑用map存一下即可

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int f = 1,x = 0;
    char ch;
    do
    {
        ch = getchar();
        if(ch == '-') f = -1;
    }while(ch < '0'||ch > '9');
    do
    {
        x = (x<<3) + (x<<1) + ch - '0';
        ch = getchar();
    }while(ch >= '0'&&ch <= '9');
    return f*x;
} 

const int MAXN = 1e5 + 10;

int n,k;
int a[MAXN][30 + 5];
int sum[MAXN][30 + 5];
vector<int>ve;
map<vector<int>,int>l;
 
int main()
{
    n = read(),k = read();
    int ans = 0;
    for(int i=1;i<=k;i++) ve.push_back(0);
    l[ve] = 0;
    for(int i=1;i<=n;i++)
    {
        int x = read();ve.clear();
        for(int j=1;j<=k;j++)
        {
            if(x&(1<<j-1))
            {
                a[i][j] = 1;
            }        
            sum[i][j] = sum[i-1][j] + a[i][j];        
            ve.push_back(sum[i][j] - sum[i][1]);
        }

        if(l.count(ve))
        {
            ans = max(ans , i - l[ve]);
        }
        else l[ve] = i;
    }
    cout << ans << endl;
} 
原文地址:https://www.cnblogs.com/wlzs1432/p/13786234.html