@[toc](Educational Codeforces Round 111 (Rated for Div. 2))
狂刷CF的时机到了,开干开干~~
2021/7/15,第1场,奥里给!!!
A-Find The Array
题目地址:A-Find The Array
题意:
给定一个s,问一个满足条件1的集合最小长度是多少
条件1:一个长度为n的集合,其中的元素要要么是1,要么是k,如果是k的话,说明集合中已经存在了k-1,k-2
解决:
最贪心的考虑,从1开始,每次增长2,直到和大于n结束,增长的次数就是我们的答案
证明:我们贪心的增长,增长的速度一定是最快的,如果正确答案是ans,那么按照最快的增长速度,所得的集合元素一定是最小的,所以实际元素个数n一定是<=ans的。
下面证明,一定可以通过不增加n的个数,将n个元素的元素和使之等于s。
因为我们按照最快的增长速度,当大于等于s的时候停止增长。所以,只会在最后一次出现大于s的情况,而最后一次出现的数是导致大于s的原因,最后一个数字过大了,那么将最后一个数分配给前面的数字就可以了。而分配的话,可以分配从1~1+2(n-1)中的任意一个。
#include <bits/stdc++.h>
using namespace std;
void work()
{
int n; cin >> n;
int cnt = 1;
for (int i = 1; i <= n; i += 2)
{
if (n > i) n -= i, cnt ++;
else break;
}
cout << cnt << endl;
}
int main()
{
int T;
cin >> T;
while (T -- )
{
work();
}
return 0;
}
B-Maximum Cost Deletion
题目:
T组数据,T大小为2000.每组数据中,给定n,a,b。n大小为100,a和b是-100到100。
第二行是一个0、1串S。现在可以不断执行操作1,最终使的S串为空串。
操作1:可以选择长度为L的连续的相同字符消掉,然后将剩下的两段子串合并,子串可以为空串,同时得到得分a*L+b
解决:
我们尝试着将所有可能加在一起,发现,如果我们合并k次的话,我们得到了的结果为a * n + k * b
所以,不管我们怎么合并,an是不变的,改变的就是kb,也就是合并次数的不同,kb的值随之改变。
那么,如果b是大于0的,我们就做尽可能多的变换,最多就是每个字符都做操作1,那么结果就是a * n + b * n
如果b小于等于0,我们就做尽可能少的操作1,那么,我们计算一下,连续的1和0总共出现多少次。然后取最小的一次,在+1,+an
#include <bits/stdc++.h>
using namespace std;
void work()
{
int n, a, b; cin >> n >> a >> b;
int s0 = 0, s1 = 0;//记录连续0出现次数,连续1出现次数
int last = -1;
for (int i = 0; i < n; i ++ )
{
int x; scanf("%1d", &x);
if (x)
{
if (last != x) s1 ++;
}
else
{
if (last != x) s0 ++;
}
last = x;
}
// cout << s0 << " " << s1 << endl;
if (b > 0) cout << n * (a + b) << "\n";
else cout << min(s0 + 1, s1 + 1) * b + n * a << "\n";
}
int main()
{
int T; cin >> T;
while (T -- )
{
work();
}
return 0;
}