Educational Codeforces Round 160 (Rated for Div. 2)题解

Rating Increase(Problem - A - Codeforces)

题目大意:给定一串数字,要求拆成a,b两个数,不能有前导0,同时a

思路:这道题如果想着尽量均分就会出bug,最好的思路是将第一位分给a,如果后面有0全部给a,从第一位不是0的数开始分给b,当然如果第一位是0,后面紧接着一位也是0,那么a就有前导0了,就不成立。按照这个思路就可以解出答案。

#include
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		string s;
		cin>>s;
		int l=s.size();
		int a=s[0]-'0',b=0,p=1;
		for(int i=1;i=b||p) printf("-1\n");
		else printf("%d %d\n",a,b); 
	}
}

Swap and Delete(Problem - B - Codeforces)

题目大意:给定一个字符串s,我们可以进行两种操作,第一种操作是删除任意一个字符,花费为1,第二种操作是交换任意两个字符,花费为0,若干次操作后,得到一个字符串t,要求t与s每一位都不相同的情况下最小花费是多少。

思路:要使花费最小,那么就要尽可能地进行交换操作,另外还要注意到,如果删除前面的字符,后面的即使交换成相异的了,也会因为删除导致的字符前移使之不成立,所以我们先统计出0和1的个数,然后从头开始进行交换操作,每操作一次,更新一下0和1的剩余个数,一旦有一个用完,那么直接退出,因为我们这里实际进行的操作是交换,也就是两两配对,后面剩下的全是1种字符,也没办法配对。最后目前得到的字符串的长度与原字符串长度的差值即为答案。

#include
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		string s;
		cin>>s;
		int a=0,b=0;
		for(int i=0;i

Game with Multiset(Problem - C - Codeforces)

题目大意:现有一个多集,我们可以对其执行两种操作:

1.add x,向多集中添加2^x这个数

2.get w,从多集中找出一个子集(一定要连续),使这个子集的和为w,如果能找到就输出yes,否则输出no。

共有n次操作。

思路:这里既然提到了2^x,那么很明显要从二进制的角度来进行考虑。问题的关键是这个w怎么处理,实际上我们可以从高位开始看,也即i从29开始,x>>i,获得实际上是x第i位及之前的数,比如6=(110)2,6>>1=(11)2=3,而6刚好可以由3个2拼出来。所以我们只要从高位进行。如下运算即可:

x-=min(x>>i,cnt[i])<

 这里x这题实际上没什么写的,最大的坑点在于对于这个子集的理解,比如放入的元素为(1,1,2,2,3,3,3),子集并非是(1,2,2,3)这种形式,而是(1,2,3)这种就可以算作子集,所以每个元素与元素只要是相邻的,放入多少个并不是得全部用完。而且不够的后面还能补。

#include
using namespace std;
int cnt[40];
int main(){
	int n;
	cin>>n;
	while(n--)
	{
		int a,x;cin>>a>>x;
		if(a==1) cnt[x]++;
		else
		{
			for(int i=29;i>=0;i--)
				x-= min(x>>i,cnt[i])<

你可能感兴趣的:(算法,数据结构)