E. The Cake Is a Lie
题目大意
D. Enchanted Artifact (1s 256Mb)
题目大意
交互题。一台机器有一个仅由a和b组成的字符串,当你输出这个字符串时,这台机器就会被摧毁,否则他会输出他的字符串和你输出的字符串的编辑距离(好东西,可以研究一些)。你最多输出 次去摧毁他。他的字符串长度不超过300,除此之外你啥都不知道。
分析
比赛时候在这自闭了半个多小时,考虑怎么去先得到字符串长度,再去判断每一位。事实证明这种构造神题不是我短时间内能解决的。以下用 表示读到的数。
先输出300个a,a的个数就是 ,因为距离是 删去的个数 + b的个数(改成a)。同理求得b的个数。得到字符串长度
输出任意一个 长的字符串,得到
设为
。将每一位翻转输出,如果得到的
(应该是
),那么翻转后的是正确的,否则翻转前的是正确的。最后输出正确字符串
这样我们用次完成任务。观察思考发现,设任意字符串为全a,则不用输出便知
是b的个数。同时最后一位不用翻转,通过a和b的个数即可推理得到,这样我们只用
次即可摧毁机器。
代码
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)
题目大意
(2e5) 个货物,每个有价钱
(1e4),你有
(2e9)的钱,可以直接一个一个买;如果一气买
个,只需要付最贵的那个的钱,求最多可以买多少个。
分析
一道不错的贪心题,自己比赛时用 方法做的,但爆了int了。
我觉得应该从答案特点分析,想办法寻找时覆盖答案比较好。考虑答案,显然贪心考虑应该是最便宜的。同时肯定尽量用优惠规则,这样剩下单个买的只能是不到 个,即
的余数。而使用优惠的方法肯定是用最贵的(不能被免费掉)去免费掉剩下最贵的,单个买的就是最便宜的那几个。这样我们只要枚举单个买的个数,在往后隔
个枚举能买的个数乘
,由于每个数字只被枚举到一次,故可以在线性时间内解决,不过排序部分还是
的。
评论里有人说桶排,这题数据组数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;
}