分M大于17的情况和M小于17两种
M大于17: 成段变化的一共只有N/M<17种,所以2^(N/M)枚举哪几段变化了,单个变化的贪心做
M小于等于17:dp[i][1<<17]来做,只要保存当前位置前的M个的值就够了
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
class FlippingBitsDiv1 {
public:
int getmin(vector<string> , int);
};
int inf = 1000000000;
string s;
int a[305];
int solveBigM(int m) {
int n = s.size();
int k = n / m;
int ans, p;
int i, j, r;
ans = inf;
for (i = 0; i < (1 << k); ++i) {
int change = 0;
p = 0;
for (j = 0; j < n; ++j)
a[j] = s[j] - '0';
for (j = n - 1; j >= 0; --j) {
if ((j + 1) % m == 0) {
if (i & (1 << (j / m))) {
p++;
change ^= 1;
}
}
a[j] ^= change;
}
for (j = 0; j < m; ++j) {
int x[2];
x[0] = x[1] = 0;
for (r = j; r < n; r += m) {
x[a[r]]++;
}
p += min(x[0], x[1]);
}
ans = min(p, ans);
}
return ans;
}
void put(int j) {
int i;
for (i = 7; i >= 0; --i) {
if (j & (1 << i))
putchar('1');
else
putchar('0');
}
}
int dp[2][1 << 17];
int solveSmallM(int m) {
int n = s.size();
int pre, now;
int i, j, k;
for (j = 0; j < (1 << m); ++j) {
dp[0][j] = 0;
dp[1][j] = inf;
}
for (now = 1, pre = 0, i = 0; i < n; ++i, now = 1 - now, pre = 1 - pre) {
for (j = 0; j < (1 << m); ++j) {
if (dp[pre][j] == inf)
continue;
int jj;
if (a[i] == (j >> (m - 1))) {
jj = ((j * 2 + a[i]) & ((1 << m) - 1));
dp[now][jj] = min(dp[now][jj], dp[pre][j]);
if (i % m == 0) {
jj = (((j ^ ((1 << m) - 1)) * 2 + (a[i] ^ 1)) & ((1 << m)
- 1));
dp[now][jj] = min(dp[now][jj], dp[pre][j] + 2);
}
} else {
jj = ((j * 2 + (a[i] ^ 1)) & ((1 << m) - 1));
dp[now][jj] = min(dp[now][jj], dp[pre][j] + 1);
if (i % m == 0) {
jj = (((j ^ ((1 << m) - 1)) * 2 + a[i]) & ((1 << m) - 1));
dp[now][jj] = min(dp[now][jj], dp[pre][j] + 1);
}
}
dp[pre][j] = inf;
}
}
int ans = inf;
for (j = 0; j < (1 << m); ++j) {
ans = min(ans, dp[pre][j]);
}
return ans;
}
int FlippingBitsDiv1::getmin(vector<string> S, int M) {
int i;
s.clear();
for (i = 0; i < S.size(); ++i)
s = s + S[i];
for (i = 0; i < s.size(); ++i)
a[i] = s[i] - '0';
if (M > 17)
return solveBigM(M);
else
return solveSmallM(M);
}