Codeforces Round #705 (Div. 2)A-C

Codeforces Round #705 (Div. 2)

打的异常痛苦的一把CF,总结原因如下:

  1. 题意没有审清,过度借助翻译软件,以后要渐渐开始阅读英文题面
  2. 比赛时间记错,导致比赛开始五分钟后才进场,状态没有调整过来

争取能够改正。

A. Anti-knapsack

给定整数n, k, 要求输出一个集合,该集合满足一下条件:

  1. 集合中的元素满足[1, n]。
  2. 任意子集中元素的和不等于k。

只要保证创造出的集合中的元素都大于\(\left \lceil k/2 \right \rceil\)并且小于等于n即可

#include<bits/stdc++.h>
#define ll int
using namespace std;
const int maxn = 2e5 + 5;

ll read(){
	char ch=getchar();
	ll x=0,f=1;
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
	return x*f;
}

void solve(){
    ll n = read(), m = read();
	cout << n - m/2 - (m%2 == 1)<< endl;
	for (int i = m/2 + (m%2 == 1); i <= n; i++) if(i != m) cout << i << " ";
	cout << endl; 
}

int main(){
    int t;cin>>t;
    while(t--){
        solve();
    }
}

B. Planet Lapituletti

在另外一个星球上,有一些时间和我们不一样的外星人。他们的一天只有h小时m分钟,他们常常通过镜子看时钟上的时间,如果他们看到他们的时间是符合他们的常识的,他们就会感到高兴。
比如:12:21,在他们的镜子上看起来就像是 15:51(沿竖轴对称)。如果他们h > 15 && m > 51即可满足条件(这里wa了好多次)

首先明确:只有当正常的时间由数字0, 1, 2, 5, 8组成时,在镜子上才是正常的数字,其次,只要满足它们对称后的数字在一天的时间以内即可。

给定h, m,和现在的时间,要求输出下一个会让外星人感到高兴的时间。挂四层暴力即可

#include<bits/stdc++.h>
#define ll int
using namespace std;
const int maxn = 2e5 + 5;

ll read(){
	char ch=getchar();
	ll x=0,f=1;
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
	return x*f;
}

int turn(int a)
{
	if (a == 2) return 5;
	if (a == 5) return 2;
	return a;
}

void solve(){
    ll h = read(), m = read();
	ll nh, nm, a[5] = {0, 1, 2, 5, 8};
	scanf("%d:%d", &nh, &nm);
	for (int i = 0; i < 5; i++)
	for (int j = 0; j < 5; j++)
	for (int k = 0; k < 5; k++)
	for (int l = 0; l < 5; l++)
		if (a[i] * 10 + a[j] < h && a[k] * 10 + a[l] < m 
		&& (a[i] * 10 + a[j]) * m + a[k] * 10 + a[l] >= nh * m + nm
		&& turn(a[l]) * 10 + turn(a[k]) < h && turn(a[j]) * 10 + turn(a[i]) < m) 
		{cout << a[i] << a[j] << ":" << a[k] << a[l] << endl; return;}
	cout << "00:00" << endl;
}

int main(){
    int t;cin>>t;
    while(t--){
        solve();
    }
}

C. K-beautiful Strings

给定字符串s和长度n以及数字k,要求找到字典序大于等于s的最小的等长字符串,满足该字符串中每个字母出现的次数都整除k。

首先,若n%k!=0,则必定不存在字符串。否则必定存在最大字符串zzz...满足条件。
因为题目条件与字母出现的次数有关,因此不妨令cnt\(_{i}\)代表某一字母出现的次数。
对于每个字母i来说,它还需要出现 \(\mathit{(k-cnt_{i} \bmod {k}) \bmod {k}}\) 次。若需要改造整个字符串,则最少需要改\( \sum_{1}^{26} (k - cnt_{i} \bmod {k}) \bmod {k}\)个字母
因此,从后往前枚举(保证最小字典序),然后对每一个字母c从c+1开始遍历所有字母,并验证是否能够更改(即更改之后能够改造它及以后所有的字母来满足条件),具体看代码。

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

ll read(){
	char ch=getchar();
	ll x=0,f=1;
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
	return x*f;
}

int f(char c)
{
	return c - 'a';
}

void solve()
{
	ll n = read(), k = read(), cnt[30];
	char s[100003];
	scanf("%s", s + 1);
	if (n % k)
	{
		puts("-1");
		return;
	}
	memset(cnt, 0, sizeof(cnt));
	int ret = 0;//需要改造的字符总数
	for (int i = 1; i <= n; i++)
	{
		cnt[f(s[i])]++;
	}
	for (int i = 0; i < 26; i++)
	{
		ret = ret + (k - cnt[i] % k) % k;
	}
	if (ret == 0)//若不需要改造
	{
		printf("%s", s + 1);
		puts("");
		return;
	}
	for (int i = n; i >= 1; i--)
	{
		cnt[f(s[i])]--;//对于s上的某一个字母,先删掉
                if (cnt[f(s[i])] % k == 0)ret -= k - 1;
		else ret++;

		int g = ret;
		for (int j = f(s[i]) + 1; j < 26; j++)
		{
			ret -= (k - cnt[j] % k) % k;
			cnt[j]++;
			ret += (k - cnt[j] % k) % k;
			if (n - i >= ret && (n - i - ret) % k == 0)
			{
				for (int h = 1; h < i; h++)
				{
					printf("%c", s[h]);
				}
				printf("%c", j + 'a');
				for (int h = 1; h <= (n - i - ret); h++)
				{
					printf("a");
				}
				for (int h = 0; h < 26; h++)
				{
					for (int o = 1; o <= (k - cnt[h] % k) % k; o++)
					{
						printf("%c", h + 'a');
					}
				}
				puts("");
				return;
			}
			ret = g;
			cnt[j]--;
		}
	}
}

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
}
posted @ 2021-03-07 14:47  Clo91eaf  阅读(211)  评论(0)    收藏  举报