Codeforces Round #610

E. The Cake Is a Lie

题目大意


D. Enchanted Artifact (1s 256Mb)

题目大意

交互题。一台机器有一个仅由a和b组成的字符串,当你输出这个字符串时,这台机器就会被摧毁,否则他会输出他的字符串和你输出的字符串的编辑距离(好东西,可以研究一些)。你最多输出 n+2 次去摧毁他。他的字符串长度不超过300,除此之外你啥都不知道。

分析

比赛时候在这自闭了半个多小时,考虑怎么去先得到字符串长度,再去判断每一位。事实证明这种构造神题不是我短时间内能解决的。以下用 q 表示读到的数。

先输出300个a,a的个数就是 300-q,因为距离是 删去的个数 + b的个数(改成a)。同理求得b的个数。得到字符串长度 n

输出任意一个 n 长的字符串,得到 q 设为 d 。将每一位翻转输出,如果得到的q<d(应该是d-1),那么翻转后的是正确的,否则翻转前的是正确的。最后输出正确字符串

这样我们用n+4次完成任务。观察思考发现,设任意字符串为全a,则不用输出便知d是b的个数。同时最后一位不用翻转,通过a和b的个数即可推理得到,这样我们只用n+2次即可摧毁机器。

代码

int main()
{
	for(int i = 1; i <= 300; i++) putchar('a');
	putchar(10); fflush(stdout);
	qa = 300-read(); if(qa == 300) return 0;
	for(int i = 1; i <= 300; i++) putchar('b');
	putchar(10); fflush(stdout);
	qb = 300-read(); if(qb == 300) return 0; //qa是a的个数 qb是b的个数
	
	n = qa+qb;
	for(int i = 1; i <= n; i++) s[i] = 'a'; s[n+1] = '\0';
	int cnta = 0, d = qb;
	
	for(int i = 1; i < n; i++)
	{
		s[i] = 'b'; printf("%s\n", s+1); fflush(stdout);
		int u = read(); if(u == 0) return 0;
		if(u < d) ans[i] = 'b';
		else ans[i] = 'a', cnta++;
		s[i] = 'a';
	}
	ans[n] = cnta < qa ? 'a' : 'b'; //推断最后一位
	printf("%s\n", ans+1);
	
	return 0;
}

B. K for the Price of One (Easy/Hard Version) (2s 256Mb)

题目大意

n(2e5) 个货物,每个有价钱 a_i(1e4),你有p(2e9)的钱,可以直接一个一个买;如果一气买 k(2 \leq k \leq n) 个,只需要付最贵的那个的钱,求最多可以买多少个。

分析

一道不错的贪心题,自己比赛时用 O(nlogn) 方法做的,但爆了int了。

我觉得应该从答案特点分析,想办法寻找时覆盖答案比较好。考虑答案,显然贪心考虑应该是最便宜的。同时肯定尽量用优惠规则,这样剩下单个买的只能是不到 k 个,即 k 的余数。而使用优惠的方法肯定是用最贵的(不能被免费掉)去免费掉剩下最贵的,单个买的就是最便宜的那几个。这样我们只要枚举单个买的个数,在往后隔 k 个枚举能买的个数乘 k,由于每个数字只被枚举到一次,故可以在线性时间内解决,不过排序部分还是 O(nlogn) 的。

评论里有人说桶排,这题数据组数T到了1e4,不值。

代码

int main()
{
	int T = read(); while(T--)
	{
		n = read(); m = read(); k = read();
		for(int i = 1; i <= n; i++) a[i] = read();
		sort(a+1, a+n+1);
		for(int i = 1; i <= n; i++) pre[i] = pre[i-1]+a[i];
		int ans = 0;
		for(int sta = 0; sta < k; sta++) //单个买的个数
		{
			if(m < pre[sta]) break;
			int anss = sta, y = m-pre[sta];
			for(int i = sta+k; i <= n; i += k) //隔k枚举
			{
				if(a[i] > y) break;
				y -= a[i];
				anss += k;
			}
			ans = max(ans, anss);
		}
		printf("%d\n", ans);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值