BestCoder Round #93 1002 / HDU 6020 思维,乱搞(待补)
HDU 6020 MG loves apple
题意:一个由数字组成的字符串,求去掉K位数字后,是否能不含前导零,且数字和被三整除。
tags:好恶心的题,不想写了,附上第一名代码。。
总的思路是:每个数字先模3,对于第i位数字,check出从第 i位到第n位是否可以删除掉 k个数字后满足条件。
// BC 93 1002 #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> typedef long long ll; #define rep(i, a, b) for (int i = a; i <= b; ++ i) const int N = 100005; using namespace std; int T, n, m, a[N], b[N][3]; char ch[N]; int solve(int x, int y, int A) { int p = min(min(x, y), A / 2), mx = 0; rep(i, max(p - 4, 0), p) mx = max(mx, i * 2 + min(((x - i) / 3 + (y - i) / 3), (A - i * 2) / 3) * 3); return mx; } bool check(int x, int y, int z, int A) { return (x >= A - solve(y, z, A)); } bool ok(int x, int y, int z, int A, int res) { //从第 i到第 n个数,有x个0,y个1,z个2,要保留A个数字,余有res if (res == 0) return check(x, y, z, A); if (res == 1) { bool flg = false; if (y && A) flg |= check(x, y - 1, z, A - 1); if (z > 1 && A > 1) flg |= check(x, y, z - 2, A - 2); return flg; } bool flg = false; if (y > 1 && A > 1) flg |= check(x, y - 2, z, A - 2); if (z && A) flg |= check(x, y, z - 1, A - 1); return flg; } int main() { scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); scanf("%s", ch); rep(i, 1, n) a[i] = ch[i - 1] - '0'; if (n - m < 2) //留下一个 { bool flg = false; rep(i, 1, n) if (a[i] % 3 == 0) flg = true; puts(flg ? "yes" : "no"); } else { m = n - m; bool flg = false; rep(i, 1, n) rep(j, 0, 2) b[i][j] = b[i-1][j] + (a[i] % 3 == j); //前 i个数中%3==j的个数 rep(i, 1, n) if (a[i] && ok(b[n][0] - b[i][0], b[n][1] - b[i][1], b[n][2] - b[i][2], m - 1, (3 - a[i] % 3) % 3)) flg = true; puts(flg ? "yes" : "no"); } } return 0; }