Codeforces Round #734 (Div. 3)

4 篇文章 0 订阅

Codeforces Round #734 (Div. 3)


A. Polycarp and Coins


题目大意:

有一个人买东西付钱,但他只有一元的钱和二元的钱, 现在他要付 n 元, 他使用一元钱的数量和二元钱数量的差值要最小, 问他付 n元使用了多少一元钱和二元钱?


解题思路:

直接将ans=n/3,便可分三种情况输出:

如果n%3==0,则说明刚好能用相同数量的一元钱和两元钱组成,直接输入两个ans即可。

如果n%3==1,说明还需要出一块钱,则输出ans+1和ans即可。

如果n%3==2,则还需多出两块前,但是为了一元钱和两元钱的差值更小,便选择出一张两元钱,则输出ans和ans+1即可。


参考代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		int ans=n/3;
		if(n%3==0)printf("%d %d\n",ans,ans);
		else if(n%3==1)printf("%d %d\n",ans+1,ans);
		else printf("%d %d\n",ans,ans+1);
	}
//	system("pause");
	return 0;
}


B1. Wonderful Coloring - 1


题目大意:

求满足以下染色条件的每种染料的染色次数为多少

1.字符要么染成红色或者绿色,要么不染色。

2.相同的颜色之间字符应该互不相同。

3.红色和绿色染色的数量相同。

解题思路:

统计字符的出现次数,对于出现次数大于等于2的便可用每种颜色分一个,对答案的贡献便为1。对于出现次数为一次的便可以进行红一个、绿一个的选择(出现次数为1的数量除2向下取整便是对答案的贡献)。


参考代码:

#include<bits/stdc++.h>
using namespace std;
int t;
char a[100];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		unordered_map<char,int>mm;
		scanf("%s",a);
		for(int i=0;i<strlen(a);i++)
		mm[a[i]]++;
		int sum=0,sum2=0;
		for(auto it:mm)
		if(it.second>=2)sum+=1;
		else sum2++;
		sum+=sum2/2;
		printf("%d\n",sum);
	}
//	system("pause");
	return 0;
}


B2. Wonderful Coloring - 2


题目大意:

求一种染色方案使得满足以下条件(用0-k表示染色的种类,0代表不进行染色):

1.数字染成1-k中颜色中的一种,或者不进行染色。

2.相同颜色的两个数字互不相同。

3.不同颜色的染色数相同。

解题思路:

对数字进行排序处理,便于统计相同数字染色相同的情况。在排序后可用,可用一个b数组来记录每一种颜色染色前的前一个染色数组,每一次染色完后进行更新来避免出现相同数字染色相同的情况。遍历数组,判断每个数字是否能染色,如果不能则continue,最后通过枚举的染色情况处理染色数量不同的情况。(多说无益,思路很难解释清楚,还得看代码)。

参考代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,k;
int b[maxn];
int ans[maxn];
struct node{
	int id;
	int val;
	int x;
}a[maxn];
bool cmp(node x,node y)
{
	return x.x<y.x;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(b,0,sizeof(b));
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i].x);
			a[i].id=i;
			a[i].val=0;
		}
 
		sort(a+1,a+1+n,cmp);
		int f=1;
		for(int i=1;i<=n;i++)
		{
			if(b[f]!=a[i].x)
			{
				a[i].val=f;
				b[f]=a[i].x;
				f++;
				if(f>k)f=1;
			}
			//ans[a[i].id]=a[i].val;
		}
		if(f!=1)
		{
			int x=0;
			for(int i=n;i>=1;i--)
			{
				if(a[i].val!=0)
				{
					a[i].val=0;
					x++;
				}
				if(x==f-1)break;
			}
		}
		for(int i=1;i<=n;i++)
		ans[a[i].id]=a[i].val;
		for(int i=1;i<=n;i++)
		printf("%d ",ans[i]);
		printf("\n");
	}
	//system("pause");
	return 0;
}


C. Interesting Story


题目大意:

从n个只包含a、b、c、d、e五种字符的单词中选择若干个,使得满足一种单词的数量大于另外四种单词的数量和,求最大的选单词数。


解题思路:

可以枚举a、b、c、d、e分别最为最大的情况,最后取最大值即可。在枚举过程中可采用贪心思想,对每一种枚举情况进行排序,降低枚举时的复杂度。当枚举a时,我们可以对字符串进行suma-sumb-sumc-sumd-sume这个值从大到小排序,循环遍历字符串时,只要出现了a的个数小于等于其他字符个数的情况就可break。其余情况也是这样。

参考代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
char s[400010];
int n,flag;
struct node{
	int suma,sumb,sumc,sume,sumd;
}a[maxn];
bool cmp(node x,node y)
{
	if(flag==1)return x.suma-(x.sumb+x.sumc+x.sumd+x.sume)>y.suma-(y.sumb+y.sumc+y.sumd+y.sume);
	if(flag==2)return x.sumb-(x.suma+x.sumc+x.sumd+x.sume)>y.sumb-(y.suma+y.sumc+y.sumd+y.sume);
	if(flag==3)return x.sumc-(x.sumb+x.suma+x.sumd+x.sume)>y.sumc-(y.sumb+y.suma+y.sumd+y.sume);
	if(flag==4)return x.sumd-(x.sumb+x.suma+x.sumc+x.sume)>y.sumd-(y.sumb+y.suma+y.sumc+y.sume);
	if(flag==5)return x.sume-(x.sumb+x.suma+x.sumc+x.sumd)>y.sume-(y.sumb+y.suma+y.sumc+y.sumd);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int maxx=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			a[i].suma=0,a[i].sumb=0,a[i].sumc=0,a[i].sumd=0,a[i].sume=0;
			scanf("%s",s);
			for(int j=0;j<strlen(s);j++)
			{
				if(s[j]=='a')a[i].suma++;
				else if(s[j]=='b')a[i].sumb++;
				else if(s[j]=='c')a[i].sumc++;
				else if(s[j]=='d')a[i].sumd++;
				else a[i].sume++;
			}
		}
		for(int i=1;i<=5;i++)
		{
			flag=i;
			sort(a+1,a+1+n,cmp);
			/*for(int j=1;j<=n;j++)
			cout<<a[j].suma<<" "<<a[j].sumb<<" "<<a[j].sumc<<endl;
			cout<<endl;*/
			int sum=0,sum1=0;
			for(int j=1;j<=n;j++)
			{
				if(i==1)
				{
					sum+=a[j].suma;
					sum1+=a[j].sumb+a[j].sumc+a[j].sumd+a[j].sume;
				}
				else if(i==2)
				{
					sum+=a[j].sumb;
					sum1+=a[j].suma+a[j].sumc+a[j].sumd+a[j].sume;
				}
				else if(i==3)
				{
					sum+=a[j].sumc;
					sum1+=a[j].sumb+a[j].suma+a[j].sumd+a[j].sume;
				}
				else if(i==4)
				{
					sum+=a[j].sumd;
					sum1+=a[j].sumb+a[j].sumc+a[j].suma+a[j].sume;
				}
				else
				{
					sum+=a[j].sume;
					sum1+=a[j].sumb+a[j].sumc+a[j].suma+a[j].sumd;
				}
				//cout<<sum<<" "<<sum1<<endl;
				if(sum<=sum1)
				{
					maxx=max(maxx,j-1);
					break;
				}
				else if(j==n)maxx=max(maxx,n);
			}
			//cout<<endl;
		}
		printf("%d\n",maxx);
	}
//	system("pause");
	return 0;
}


D1. Domino (easy version)


题目大意:

在一个n × \times ×m的网格上,可以放置 1 × \times × 2 或者 2 × \times × 1的多米若骨牌,问在n × \times ×m为偶数的情况下能否放置恰好k个1 × \times × 2的多米若骨牌。

解题思路:

对于n和m全为偶数的情况下,只能放偶数个1 × \times × 2或者2 × \times × 1的多米若骨牌,所有在这种情况下k一定要为一个偶数。

对于n和m全为奇数的情况下,不管k为奇数或者偶数,全是不可能的情况。

对于n为奇数的情况,可以先放m/2个使得变为n和m全为偶数的情况进行判断。

对于m为奇数的情况,可以发现k为偶数可以满足情况,但是如果k>m/2*n的情况需要特判,因为这种情况是不可能满足的。


参考代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d",&n,&m,&k);
		if(n%2==0&&m%2==0)
		{
			if(k%2==0)printf("YES\n");
			else printf("NO\n");
		}
		else
		{
			if(n%2==1&&m%2==1)printf("NO\n");
			else if(n%2==1)
			{
				if(n==1)
				{
					if(k==m/2)printf("YES\n");
					else printf("NO\n");
				}
				else
				{
					int x=m/2;
					if(k-x<0)printf("NO\n");
					else if((k-x)%2==0)printf("YES\n");
					else printf("NO\n");
				}
			}
			else
			{
				if(m==1)
				{
					if(k==0)printf("YES\n");
					else printf("NO\n");
				}
				else
				{
					if(k>m/2*n)printf("NO\n");
					else
					{
						if(k%2==0)printf("YES\n");
						else printf("NO\n");
					}
				}
			}
		}
	}
//	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值