【题目链接】:http://acm.hdu.edu.cn/showproblem.php?pid=6020

【题意】



给你一个长度为n的数字,然后让你删掉k个数字,问你有没有删数方案使得剩下的N-K个数字是3的倍数;

【题解】



这里我们枚举最后N-K个数字它的最高位是第几位;

这样我们就能在枚举最高位的时候直接判断这个数字是不是0;这样对合法性的处理就简单很多了;

我们枚举第i位是最高位,言外之意就是说前i-1个数字已经全部被删掉了;

则我们要在i+1..n这些数字里面再删掉k-i+1个数字才行;

这里设i+1..n这些数字的和对3的取余结果为rest



如果rest为1

我们先在i+1..n里面删掉1个取余结果为1的数字或者在i+1..n里面删掉2个取余结果为2的数字;后续的工作我们等下再说.

如果rest为2

我们先在i+1..n里面删掉1个取余结果为2的数字或者在i+1..n里面删掉2个取余结果为1的数字;

至此我们把问题转换成

在i+1..n里面删掉k-i+1-x个数字(x是我们刚才因为rest不等于0先假设删掉的数字)然后要求i+1..n所有的数字的和%3的结果为0;

这里我们只要考虑1+2和0两种形式了;

对于1+2类型的,我们只要考虑最多出现2组配对;

即两组1+2

因为如果你出现了3组1+2,其实也就是3个1和3个2了;

所以我们枚举出现了几组”1+2”类型->i然后i∈[0..2]

然后1剩下r1-i个,2剩下r2-i个,然后1能够选(r1-i)/3*3个,2能够选(r2-i)/3*3个;

之所以3个3个地选,是保证删除这些数字之后取余结果仍然保持0;

然后3个3个地选完之后,再看看余为0的个数有多少个;看够不够凑足k-i+1-x个数字;够的话就可行;

这里没办法考虑到删掉n-1个数字然后结果为0的情况;

所以要特判.



【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define ps push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x) typedef pair<int, int> pii;
typedef pair<LL, LL> pll; const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
const double pi = acos(-1.0);
const int N = 1e5+100; int n, k;
char s[N];
int a[N],t[N],hzh[N][3]; bool ok(int r0, int r1, int r2, int k)
{
if (r0 < 0 || r1 < 0 || r2 < 0 || k < 0) return false;
if (k == 0) return true;
rep1(i, 0, 2)
{
if (r1 < i || r2 < i) break;
if (2 * i > k) break;
int restk = k - 2 * i;
if (restk == 0) return true;
int d = (r1 - i) / 3 * 3 + (r2 - i) / 3 * 3;
if (d < restk)
{
if (d + r0 >= restk) return true;
}
else//d>=restk
{
restk %= 3;
if (r0 >= restk)
return true;
}
}
return false;
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
int T;
rei(T);
while (T--)
{
rei(n), rei(k);
scanf("%s", s + 1);
rep1(i, 1, n)
{
a[i] = s[i] - '0';
t[i] = a[i] % 3;
}
rep1(i, 0, 2) hzh[n + 1][i] = 0;
rep2(i, n, 1)
{
rep1(j, 0, 2) hzh[i][j] = hzh[i + 1][j];
hzh[i][t[i]]++;
}
int rest = (hzh[1][1] + hzh[1][2] * 2) % 3;
bool fi = false;
rep1(i, 1, n)
{
if (a[i] > 0)
{
if (rest == 0 && ok(hzh[i + 1][0], hzh[i + 1][1], hzh[i + 1][2], k - i + 1)) {
fi = true; break;
}
if (rest == 1 && (ok(hzh[i+1][0],hzh[i+1][1]-1,hzh[i+1][2],k-i)||ok(hzh[i+1][0],hzh[i+1][1],hzh[i+1][2]-2,k-i-1))) {
fi = true; break;
}
if (rest == 2 && (ok(hzh[i + 1][0], hzh[i + 1][1] - 2, hzh[i + 1][2], k - i-1) || ok(hzh[i + 1][0], hzh[i + 1][1], hzh[i + 1][2] - 1, k - i))) {
fi = true; break;
}
}
rest = (rest - t[i] + 3) % 3;
}
if (k == n - 1 && hzh[1][0] > 0) fi = true;
if (fi) puts("yes"); else puts("no");
}
//printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}

【BestCoder Round #93 1002】MG loves apple的更多相关文章

  1. 【BestCoder Round #93 1001】MG loves gold

    [题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=6019 [题意] 每次选择一段连续的段,使得这一段里面没有重复的元素; 问你最少选多少次; [题解] ...

  2. 【BestCoder Round #93 1004】MG loves set

    [题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=6022 [题意] 让你求一个集合的子集数目; 这个子集有要求; 即: 它所有元素的平方的和小于它所有 ...

  3. 【HDU 6020】 MG loves apple (乱搞?)

    MG loves apple  Accepts: 20  Submissions: 693  Time Limit: 3000/1500 MS (Java/Others)  Memory Limit: ...

  4. 贪心/二分查找 BestCoder Round #43 1002 pog loves szh II

    题目传送门 /* 贪心/二分查找:首先对ai%=p,然后sort,这样的话就有序能使用二分查找.贪心的思想是每次找到一个aj使得和为p-1(如果有的话) 当然有可能两个数和超过p,那么an的值最优,每 ...

  5. 暴力+降复杂度 BestCoder Round #39 1002 Mutiple

    题目传送门 /* 设一个b[]来保存每一个a[]的质因数的id,从后往前每一次更新质因数的id, 若没有,默认加0,nlogn复杂度: 我用暴力竟然水过去了:) */ #include <cst ...

  6. 矩阵快速幂---BestCoder Round#8 1002

    当要求递推数列的第n项且n很大时,怎么快速求得第n项呢?可以用矩阵快速幂来加速计算.我们可以用矩阵来表示数列递推公式比如fibonacci数列 可以表示为 [f(n)   f(n-1)] = [f(n ...

  7. Manacher BestCoder Round #49 ($) 1002 Three Palindromes

    题目传送门 /* Manacher:该算法能求最长回文串,思路时依据回文半径p数组找到第一个和第三个会文串,然后暴力枚举判断是否存在中间的回文串 另外,在原字符串没啥用时可以直接覆盖,省去一个数组空间 ...

  8. 二分图判定+点染色/并查集 BestCoder Round #48 ($) 1002 wyh2000 and pupil

    题目传送门 /* 二分图判定+点染色:因为有很多联通块,要对所有点二分图匹配,若不能,存在点是无法分配的,no 每一次二分图匹配时,将点多的集合加大最后第一个集合去 注意:n <= 1,no,两 ...

  9. hdu 6020 MG loves apple 恶心模拟

    题目链接:点击传送 MG loves apple Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Ja ...

随机推荐

  1. svn基本命令使用

    1.svn help:可以通过该命令查看svn的所有操作命令,包括命令的缩写 2.首先需要从svn库中checkout对应的项目: (1)svn项目路径为svn://192.168.1.1/mypro ...

  2. KMLLayer

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. python进程间通信 queue pipe

    python进程间通信 1 python提供了多种进程通信的方式,主要Queue和Pipe这两种方式,Queue用于多个进程间实现通信,Pipe是两个进程的通信 1.1 Queue有两个方法: Put ...

  4. 抽象类 abstract class 接口

    一.抽象类 1.没有具体的实例. 不可实例化,不能创建对象. 2.抽象类有构造器. 二.abstract 方法. 1.没有方法体. 子类必须重写抽象类的所有抽象方法,才能实例化,否则子类也为抽象类. ...

  5. 【转载】【技巧总结】PyCharm怎么克隆github上开源的项目

    PyCharm怎么clone github上开源的项目 一.先要确保PyCharm正确的配置了Git   如果你已经在PyCharm中配置好了Git,可以跳过此步骤,直接看下一步.   那么怎么在Py ...

  6. python 面向对象编程语言

  7. oracle 共享服务器监控

    1.   观察sga的使用情况 select * from v$sgastat where pool=’large pool’; 2.   观察调度程序是否充足: 首先看每个调度程序的忙闲: sele ...

  8. Black-White-Blocks

    微信小程序黑白块游戏 代码如下: //play.js // play var app = getApp() Page({ data: { typeName: '计时模式', score: 0, tim ...

  9. MacOS局域网访问Windows7共享文件

    配置步骤 Windows7 进入[控制面板]-[网络和共享中心]-[高级共享设置] 启用网络发现 启用文件和打印机共享 选择要共享的文件或文件夹,点击[共享]-[特定用户] 选择Windows7当前登 ...

  10. python 不定长参数*args