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; }