Codeforces Round #734 (Div. 3)


A、Polycarp and Coins

题目链接:Polycarp and Coins

题意:你有两种硬币:一种是面值为一元的、另一种是面值为二元的,现在给出一个数值,要求由尽可能数量相同两种硬币组成这个值,输出一元硬币和二元硬币的数量。

思路:首先清楚两个硬币组合是为3,对于所有数值是3的倍数的话,都可以取到相等的,如果对3取模为1就加一个一元硬币,取模为二就加一个二元硬币,两者的基础值都是数值除3。

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <iomanip>
#include <cstring>
#include <string>
#include <vector>
#include <math.h>
#include <bitset>
#include <cctype>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(a, b, c)  for(int a = b; a <= c; a ++)
#define drep(a, b, c) for(int a = b; a >= c; a --)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define endl '\n'
#define ccn cout << '\n'
const double PI = acos(-1.0);
const double eps = 1e-6;
ll qpow(ll a, ll b){
	ll res = 1; while(b){if(b&1)res*=a; a*=a;b>>=1;} return res;
}
inline int read(){
	int s=0,w=1; char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}

int main ()
{
	int t;
	cin >> t;
	while(t--)
	{
		int n;
		cin >> n;
		int a = n/3;
		int b = n - 2*a;
		while(b - a >= 2)
		{
			b -= 2;
			a++;
		}
		cout << b << " " << a << endl; 
	}
	return 0;
}



B1、Wonderful Coloring - 1

题目链接:Wonderful Coloring - 1

题意:涂色题,要么涂红色或者绿色还是不涂三种选择,要求满足字符串中每种字母不会被两种颜色同时涂到,而且涂红色的次数应该和绿色想等,
求红色最多涂了多少。

思路:很简单的题,数据范围也很小,首先是设置一个数组,统计每种字母出现的次数,然后遍历这个数组,如果次数大于等于2:ans直接加一,如果次数小于2:则left加一。最后ans加上left/2的值就是答案了。

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <iomanip>
#include <cstring>
#include <string>
#include <vector>
#include <math.h>
#include <bitset>
#include <cctype>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(a, b, c)  for(int a = b; a <= c; a ++)
#define drep(a, b, c) for(int a = b; a >= c; a --)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define endl '\n'
#define ccn cout << '\n'
const double PI = acos(-1.0);
const double eps = 1e-6;
ll qpow(ll a, ll b){
	ll res = 1; while(b){if(b&1)res*=a; a*=a;b>>=1;} return res;
}
inline int read(){
	int s=0,w=1; char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}

int ch[28], t;

int main ()
{
	cin >> t;
	while(t--)
	{
		for(int i = 1; i <= 26; i++)
		{
			ch[i] = 0;
		}
		
		string s;
		cin >> s;
		
		for(int i = 0; i < s.size(); i++)
		{
			ch[s[i]-'a'+1] ++;
		}
		
		int left = 0, ans = 0;
		
		for(int i = 1; i <= 26; i++)
		{
			if (ch[i] >= 2)
			{
				ans ++;
			}
			
			if (ch[i] == 1)
			{
				left ++;
			}
		}
		
//		cout << left << " " << ans << enld;
		
		ans += left/2;
		
		cout << ans << endl;
		
	}
	return 0;
}

B2、 Wonderful Coloring - 2

题目链接:Wonderful Coloring - 2

题意:是上一题的增加版本,输入一个n个元素的数组和k种颜色,尽量给数组涂色,满足以下要求:可以涂k种颜色种的任意一种也可以不涂、每种颜色使用的数量必须相等、一个数不允许被同一种颜料涂两次、尽量给数组涂上最多种的颜色。

思路:我们可以简单的想到,如果这个数出现的次数大于等于k的时候,所有这个数就直接涂1到k剩下的都是零。对于剩下的数,我们依次涂1-k就可以了,只不过注意在最后可能会剩下来一些地方情况,即剩下的数不够涂k次,导致最后每种颜色涂的次数不相等,这里我卡住了一个地方,那就是可能会给一个色涂上了一个重复的颜色,所以我们这里可以用一个结构体排序的方式来进行处理。

吐槽:这个题真的是,没注意到直接过去会重复涂,中间实现的时候自闭了,以为自己码不出来已经有思路的题,结果是思路出错了,真的无语。

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <iomanip>
#include <cstring>
#include <string>
#include <vector>
#include <math.h>
#include <bitset>
#include <cctype>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(a, b, c)  for(int a = b; a <= c; a ++)
#define drep(a, b, c) for(int a = b; a >= c; a --)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define endl '\n'
#define ccn cout << '\n'
const double PI = acos(-1.0);
const double eps = 1e-6;
ll qpow(ll a, ll b){
	ll res = 1; while(b){if(b&1)res*=a; a*=a;b>>=1;} return res;
}
inline int read(){
	int s=0,w=1; char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}
int t, a[200005], b[200005], c[200005], ans[200005], n, k;
struct node 
{
	int val, pos, ans;
};
node x[200005];
bool cmp1(node p, node q)
{
	return p.val < q.val;
}
bool cmp2(node p, node q)
{
	return p.pos < q.pos;
}
int main ()
{
	cin >> t;
	while(t--)
	{
		cin >> n >> k;
		for(int i = 1; i <= n; i ++)
		{
			cin >> x[i].val;
			x[i].pos = i;
			b[x[i].val]++;
		}
		
		int sum = 0;
		for(int i = 1;i <= n; i++)
		{ 
			if (b[x[i].val] < k) sum ++;
		}
		
		sort(x+1, x+1+n, cmp1);
		
		int top = sum/k*k, num = 1, mark = 1;
		int flag = 1;
		for(int i = 1; i <= n; i ++)
		{
			if (b[x[i].val] >= k)
			{
				x[i].ans = ++c[x[i].val];
				if (x[i].ans > k) x[i].ans = 0;
			}
			else
			{
				if (num <= top)
				{
					num++;
					x[i].ans = mark ++;
					if (mark > k) mark = 1;
				}
			}
		}
		sort(x+1, x+1+n, cmp2);
		// ==== ==== ==== ==== ==== ==== 
		for(int i = 1; i<= n; i++)
		{
			cout << x[i].ans << " ";
		}
		cout << endl;
		for(int i = 1; i <= n; i++)
		{
			c[x[i].val] = 0;
			b[x[i].val] = 0;
			x[i].ans = 0;
		}
	}
	return 0;
}

C、C - Interesting Story

题目链接:Interesting Story

题意:有t组测试样例,每组有n个单词,所有单词都只由a、b、c、d和e一共
五种字母构成,对于一个单词,如果有一种字母总数比除它以外所有字母数的大,那么对于这个单词来讲就是符合要求的,同样的对于构成这样的一个文章也是如此,求一个文章最多由多少个单词构成且符合要求。

思路:我也是思考好一会,最后看了下别人的题解,恍然大悟,这个题不难。首先我们可以注意到,对于文章来讲不一定要其中的每一个单词都满足要求,我们只对总体要求满足就可以,那么我们肯定选取最大满足的单个单词,也是需要排序一下,我们思考一下复杂度,因为只有五种字母而且所有单词的总长度不大于2e5,所以我们直接枚举五种字母分别猜想为最大的结果,最后取结果中最大的即可,不会TLE。

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <iomanip>
#include <cstring>
#include <string>
#include <vector>
#include <math.h>
#include <bitset>
#include <cctype>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(a, b, c)  for(int a = b; a <= c; a ++)
#define drep(a, b, c) for(int a = b; a >= c; a --)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define endl '\n'
#define ccn cout << '\n'
const double PI = acos(-1.0);
const double eps = 1e-6;
ll qpow(ll a, ll b){
	ll res = 1; while(b){if(b&1)res*=a; a*=a;b>>=1;} return res;
}
inline int read(){
	int s=0,w=1; char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}
const int N = 200005;
int a[N], b[N], c[N], d[N], e[N], n, t;
string s[N];
bool cmp(int a, int b)
{
	return a > b;
}
int main ()
{
	cin >> t;
	while(t--)
	{
		cin >> n;
		for(int i = 1; i <= n; i ++)
		{
			cin >> s[i];
			int aa = 0, bb= 0, cc = 0, dd = 0, ee = 0;
			for(int j = 0; j < s[i].size(); j++)
			{
				if (s[i][j] == 'a') aa++;
				if (s[i][j] == 'b') bb++;
				if (s[i][j] == 'c') cc++;
				if (s[i][j] == 'd') dd++;
				if (s[i][j] == 'e') ee++;
			}
			a[i] = 2*aa - s[i].size();
			b[i] = 2*bb - s[i].size();
			c[i] = 2*cc - s[i].size();
			d[i] = 2*dd - s[i].size();
			e[i] = 2*ee - s[i].size();
		}
		sort(a+1, a+1+n, cmp);
		sort(b+1, b+1+n, cmp);
		sort(c+1, c+1+n, cmp);
		sort(d+1, d+1+n, cmp);
		sort(e+1, e+1+n, cmp);
		int sum = 0, ans=0;
		for(int i = 1; i <= n; i++)
		{
			sum += a[i];
			if (sum > 0) ans=max(ans, i);
		}
		sum = 0;
//		cout << ans << endl;
		//====
		for(int i = 1; i <= n; i++)
		{
			sum += b[i];
			if (sum > 0) ans=max(ans, i);
		}
		sum = 0;
//		cout << ans << endl;
		//====
		for(int i = 1; i <= n; i++)
		{
			sum += c[i];
			if (sum > 0) ans=max(ans, i);
		}
		sum = 0;
//		cout << ans << endl;
		//====
		for(int i = 1; i <= n; i++)
		{
			sum += d[i];
			if (sum > 0) ans=max(ans, i);
		}
		sum = 0;
//		cout << ans << endl;
		//====
		for(int i = 1; i <= n; i++)
		{
			sum += e[i];
			if (sum > 0) ans=max(ans, i);
		}
		//====
//		cout << "ans = ";
		cout << ans << endl;
	}
	return 0;
}

D1 Domino (easy version)

题目链接:Domino(easy version)

题意:有一个n乘以m的空间,空间为偶数,多米诺骨牌是一个面积为1乘以2的矩形,在这个空间里面有两种表示方法,一种是竖着、一种方式横着,题目要求能不能刚好k个横着,剩下都必须竖着,而且必须占满所有的空间。

思路:首先,我们从空间数是偶数开始,我可以发现宽和高不可以都是奇数,至少有一个或者两个都是偶数。然后我们再设想当高不为奇数的时候,无论宽度是奇数还是偶数都可以用竖着的骨牌填满,同理如果是高度是奇数,那么宽度一定是偶数,那么刚好可以用一排横着的先填满,这个情况可以看做是优先填满然后再优先竖着的。最后我们知道两个竖着的换成两个横着的,不过这里要注意一个小点,就是必须是横着连续的两个竖着的。最后这个题没有什么需要码力的地方,只要按照思路判断条件就可以了。

吐槽:不知道为什么放在D1,我觉得可以放在B2前面哇。

#include <bits/stdc++.h>
using namespace std;
int main ()
{
	int n, m, k, t;
	cin >> t;
	while(t--)
	{
		cin >> n >> m >> k;
		int x = (n/2)*(m/2);
		int h = 0;	
		if (n%2 == 1)
		{
			h += m/2;
		}
		if (k == h || ((k-h)%2==0 && (k-h)/2 <= x) && k>= h)
		{
			cout << "YES" << endl;
		}
		else
		{
			cout << "NO" << endl;
		}
	} 
	return 0;
}

D2、Domino (hard version)

题目链接:Domino (hard version)

题意:看过D1了吗,就是要求把多米诺骨牌打出来,为了表示不相同的多米诺骨牌,就是一个多米诺骨牌用两个连续的小写字母表示,然后相邻的骨牌肯定不能用同一种小写字母表示(废话 )。

思路:由之前可以知道最多只会有一个边会是奇数,如果有这个奇数边,我们先可以用e和f来单独处理这一个边,然后剩下部分就是一个偶数矩阵,我是选择用c和d交叉表示竖着的骨诺牌,最后根据需要的从左上角开始处理生成横着的多米诺骨牌,这样就可以好处理很多。

吐槽:这居然是cf的2100分题,太顶了吧,前面D1也是,太那啥玄学了,我还小心翼翼的处理每个情况。结果一不小心就写太多了,来贴贴代码了。(重复部分请无视哇

#include <bits/stdc++.h>
using namespace std;

char a[105][105];

void output(int n, int m)
{
	for(int i = 1; i <= n; i++)
	{
//		cout <<  i << " : " ;
		for(int j = 1; j <= m; j++)
		{
			cout << a[i][j];
		}
		cout << endl;
	}
}

int main ()
{
	int n, m, k, t;
	cin >> t;
	while(t--)
	{
		cin >> n >> m >> k;
		
		int x = (n/2)*(m/2);
			
		int h = 0;	
		if (n%2 == 1)
		{
			h += m/2;
		}
		
		if (k == h || ((k-h)%2==0 && (k-h)/2 <= x) && k>= h)
		{
			cout << "YES" << endl;
			if (n%2 == 1 && m%2==0)
			{
				// ==== ==== ==== ==== ==== 
				for(int i = 1; i <= m; i+=2)
				{
					if((i+1)/2%2 == 1)	a[n][i] = a[n][i+1] = 'e';
					else a[n][i] = a[n][i+1] = 'f';
				}
				for(int i = 1; i <= n-1; i+=2)
				{
					for(int j = 1; j <= m; j++)
					{
						if ( (i+1)/2%2==1 )
						{
							if (j%2 == 1)
							{
								a[i][j] = a[i+1][j] = 'c';
								
 							}
							else
							{
								a[i][j] = a[i+1][j] = 'd';
							}
						}
						else
						{
							if (j%2 == 1)
							{
								a[i][j] = a[i+1][j] = 'd';
							}
							else
							{
								a[i][j] = a[i+1][j] = 'c';
							}
						}
					}
				}
				// ==== ==== ==== ==== ==== 
				int y = (k - h)/2, cnt = 0;
//				cout << "y : "<< y << endl;
				for(int i = 1; i <= n-1; i +=2)
				{
					if(cnt >= y) break; 
					for(int j = 1; j <= m; j += 2)
					{
						if(cnt >= y) break;
						if( (j+1)/2%2 == 1)
						{
							a[i][j] = a[i][j+1] = 'a';
							a[i+1][j] = a[i+1][j+1] = 'b';
							cnt++;
						}
						else
						{
							a[i][j] = a[i][j+1] = 'b';
							a[i+1][j] = a[i+1][j+1] = 'a';
							cnt++;
						}
					}
				}
				// ==== ==== ==== ==== ====
			}
			else if (n%2==0 && m%2==1)
			{
				//---------------------------------------------------------------
				for(int i = 1; i <= n; i+=2)
				{
					if((i+1)/2%2 == 1)	a[i][m] = a[i+1][m] = 'e';
					else a[i][m] = a[i+1][m] = 'f';
				}
				// ==== ==== ==== ====
				for(int i = 1; i <= n; i+=2)
				{
					for(int j = 1; j <= m-1; j++)
					{
						if ( (i+1)/2%2==1 )
						{
							if (j%2 == 1)
							{
								a[i][j] = a[i+1][j] = 'c';
								
 							}
							else
							{
								a[i][j] = a[i+1][j] = 'd';
							}
						}
						else
						{
							if (j%2 == 1)
							{
								a[i][j] = a[i+1][j] = 'd';
							}
							else
							{
								a[i][j] = a[i+1][j] = 'c';
							}
						}
					}
				}
				// ==== ==== ==== ==== ==== 
				int y = (k - h)/2, cnt = 0;
//				cout << "y : "<< y << endl;
				for(int i = 1; i <= n; i +=2)
				{
					if(cnt >= y) break; 
					for(int j = 1; j <= m-1; j += 2)
					{
						if(cnt >= y) break;
						if( (j+1)/2%2 == 1)
						{
							a[i][j] = a[i][j+1] = 'a';
							a[i+1][j] = a[i+1][j+1] = 'b';
							cnt++;
						}
						else
						{
							a[i][j] = a[i][j+1] = 'b';
							a[i+1][j] = a[i+1][j+1] = 'a';
							cnt++;
						}
					}
				}
			}
			else if (n%2 == 0 && m%2== 0)
			{
				for(int i = 1; i <= n; i+=2)
				{
					for(int j = 1; j <= m; j++)
					{
						if ( (i+1)/2%2==1 )
						{
							if (j%2 == 1)
							{
								a[i][j] = a[i+1][j] = 'c';
								
 							}
							else
							{
								a[i][j] = a[i+1][j] = 'd';
							}
						}
						else
						{
							if (j%2 == 1)
							{
								a[i][j] = a[i+1][j] = 'd';
							}
							else
							{
								a[i][j] = a[i+1][j] = 'c';
							}
						}
					}
				}
				// ==== ==== ==== ==== ==== 
				int y = (k - h)/2, cnt = 0;
//				cout << "y : "<< y << endl;
				for(int i = 1; i <= n; i +=2)
				{
					if(cnt >= y) break; 
					for(int j = 1; j <= m; j += 2)
					{
						if(cnt >= y) break;
						if( (j+1)/2%2 == 1)
						{
							a[i][j] = a[i][j+1] = 'a';
							a[i+1][j] = a[i+1][j+1] = 'b';
							cnt++;
						}
						else
						{
							a[i][j] = a[i][j+1] = 'b';
							a[i+1][j] = a[i+1][j+1] = 'a';
							cnt++;
						}
					}
				}
			}
			
			output(n, m);
		}
		else
		{
			cout << "NO" << endl;
		}
	} 
	return 0;
}



  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值