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;
}
原文地址:https://www.cnblogs.com/sbfhy/p/6659266.html