Codeforces Round #734 (Div. 3) 题解

前言

蒟蒻过来补题,大佬误嘲 (QAQ)D2、E、F题暂时不在能力范围内呀~~以后补上

A. Polycarp and Coins

A题原题戳这里

题目的大致意思:给定一正整数为商品的总价,要求尽量用相等数量的面值为1伯勒和2伯勒的钱去买该商品。(水题无疑了)

题解:

#include<iostream>
using namespace std;
 
int main()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int sum=n/3;
        if(sum*3==n)cout<<sum<<" "<<sum<<endl;
        else{
            if(n-sum*3==2) cout<<sum<<" "<<sum+1<<endl;
            else cout<<sum+1<<" "<<sum<<endl;
        }
    }
    return 0;
}

B1.Wonderful Coloring - 1

B1题原题戳这里

题目的大致意思:将给定字符串的每个字符进行涂色,每个字符可以涂也可以不涂,要求两种颜色的字符数量相等,但是同一种字符不能图相同颜色。(还是水题)

题解:

#include<iostream>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        int a[26]={0};//开始的时候把这个定义在外面了,就是错误答案
        int sum=0;
        for(int i=0;i<s.size();i++){
            a[s[i]-'a']++;
            if(a[s[i]-'a']<=2)sum++;
        }
        cout<<sum/2<<endl;
    }
    return 0;
}

B2.Wonderful Coloring - 2

B2题戳这里

题目的大致意思:这题是B1题的升级版,给定k种颜色能够使用,给相同数字涂不同颜色,相同颜色不能有相同颜色,每种颜色的数字个数要相同,最后输出每个数字涂色的编号,多种涂法输出任意一种。(从这一题开始难度提升了)

解题思路: 先将相同的数字进行记数,如果它重复的个数大于已有的颜色数目,就需要用到所有的颜色。剩下没有重复或者有重复但是重复个数不到k的就可以从1到k进行循环涂色,这样就能保证每种颜色最后的数目相同了(不够循环整数次的多的就不涂色)。剩下的就看代码实现啦!绕了好久才理清楚(哭唧唧~)
题解:

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 2e5+10;
int a[N];//用于储存最初的数组并进行排序方便统计重复次数
int b[N];//用于储存除去重复个数大于k的数字后剩下的数字
int c[N]; //用于储存最初的数组,并保持不变
queue<int> q[N];//利用先进先出的优势储存每个数据涂色的编号
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n,k;
		cin>>n>>k;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			c[i] = a[i];//将输入的数据拷贝到数组储存起来,方便后面涂色使用
		}
		sort(a+1,a+n+1); //排序后方便统计重复次数啦
		int j=1;
		int cnt=1;
		b[1]=a[1];//第一个数据不要漏掉了
		for(int i=2;i<=n;i++){ 
			if(a[i]==a[i-1]) cnt++;//统计重复次数
			else cnt=1;
			if(cnt<=k){
				j++;
				b[j]=a[i];//将筛掉重复次数大于k次的数据储存起来
			}
		}
		int d = j/k*k; //利用能够整除的次数求能在循环内的数据个数 ,保证所有颜色数量相等
		int now=1;//涂色编号
		for(int i=1;i<=d;i++){
			q[b[i]].push(now);//就算还有数据重复,但是重复个数小于k都会被后一次的涂色所覆盖,不会导致相同颜色有重复的情况
			now++;
			if(now>k) now=1;
		}
		//这时候输出的时候c数组就要起作用啦!
		for(int i=1;i<=n;i++){
	
			if(q[c[i]].empty()) cout<<"0 ";
			else{
			cout<<q[c[i]].front()<<" ";
				q[c[i]].pop();
			}
		}
		cout<<endl;
	}	
	return 0;
}

C.Interesting Story

C题原题戳这里

题目的大致意思:给定几个字符串,字符串都只由a,b,c,d,e组成,将字符串组装起来,使得其中一个字母的重复次数大于剩余所有字母的数目总和,输出使用字符串的最大个数。

解题思路:将每一个字符串的每一个字母的个数先进行统计,然后再根据题目的运算(字母个数-剩余其它字母总和)并把数据储存起来。最后对每一个字符串的相同字母所求的对应运算差进行排序,之后从高位开始求和并记录所用字符串的个数,当和的值小于或者等于0时就是当前字母能满足题意的临界状态,这时的字符串个数就是该字母满足题意的个数。同理求5个字母分别的最大个数之后取最大值就是最终需要输出的数值。这里似乎需要用到二维数组对每一个字符串的5个字母分别记录,但是二维数组不方便进行每一行或者每一列的排序,就考虑用到vector容器(现在来看代码加深理解吧,借鉴了大佬们的代码)

题解:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int>w[5];//储存每个字符串种每个字母的数据差(题中运算)
int main() {
	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		string s;
		for (int i = 0; i < n; i++) {
			cin >> s;
			int abc[5] = { 0 };
			for (int j = 0; j < s.size(); j++) {
				abc[s[j] - 'a']++;//每个字符串中的每个字母计数
			}
			for (int j = 0; j < 5; j++) {
				w[j].push_back(abc[j] * 2 - s.size());//实质上是abc[j]-(s.size()-abc[j])
			}
		}
		int ans = 0;
		for (int i = 0; i < 5; i++) {
			sort(w[i].begin(), w[i].end());//每个字母相应数据排序
			int sum = 0;
			int temp = 0;
			for (int j = n - 1; j >= 0; j--) {
				sum += w[i][j];
				if (sum > 0) temp++;
				else break;
			}
			if (temp > ans) ans = temp;
		}
		cout << ans<<endl;
		for (int i = 0; i < 5; i++) w[i].clear();//一定记得清空容器中的数据,一遍下一个用例使用
	}
	return 0;
}

D1. Domino (easy version)

D1题原题戳这里

题目的大致意思:这题好像家里装修贴地砖一样,有横着的砖块和竖着的砖块,规格都是占两格。现在给n*m(长m宽n)的面积给你,需要你用砖块将它填满并且使用的横着的砖块恰好是k个,可以就输出YES,不可以就输出NO。

解题思路:分情况讨论,当n为奇数,m为偶数时;n为偶数,m为奇数时;n和m同为奇数或者同为偶数时。n为奇数时必定有一行要用到横着的地砖,这时候如果横着的不够用,就一定不行;m为奇数时同理;当n和m同为奇数或偶数时,k为奇数时一定不行
题解:

#include<iostream>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n, m, kh;
        cin >> n >> m >> kh;
        int kv = n * m / 2 - kh;
        if (n & 1)//假如宽n是奇数(位运算判断奇偶,按照二进制来看)
        {
            kh -= m / 2;
            if (k < 0)
            {
                cout << "NO\n";
                continue;
            }
        }
        else if (m & 1) //假如长m为奇数
        {
            kv -= n / 2;
            if (kv < 0)
            {
                cout << "NO\n";
                continue;
            }
        }
        if ((kh & 1) || (kv & 1))//n和m同为奇数或者偶数
        {
            cout << "NO\n";
            continue;
        }
        cout << "YES\n";
    }
    return 0;
}

题解来源戳这里

总结

又是烧脑的一天,头发-1-1-1-1…QAQ

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值