最近打的超级差,实力和状态都不如以前,设立计划,往前刷20场cf,目标还是这个暑假rating上1900,并且将基础课算法刷完,这个暑假的重心放在提升思维和对基础算法的模板的熟悉。等到思维提升了再去加强算法的掌握度,时刻注意不要急慢慢来,当初不也是高三一个学期提升200分嘛,稳扎稳打,又不是智商问题
大概这就是杯爷的赛后cf吧,我这补题,人在那叉人
A - Polycarp and Coins
题意:求x + 2y = c
思路:直接计算即可
代码
#include <bits/stdc++.h>
#define int long long
#define ios ios::sync_with_stdio(false); cin.tie(0);
using namespace std;
inline void solve() {
int n; cin >> n;
int t1 = n / 3, t2 = n - t1;
if(t2 % 2) t1++;
cout << t1 << " " << t2 / 2 << endl;
return ;
}
signed main() {
ios;
int t; cin >> t;
while(t--) solve();
return 0;
}
B1. Wonderful Coloring - 1
题意:将n个字母染色,要求如下:
1.字符串的每个字母要么被涂成一种颜色(红色或绿色),要么没有涂;
2.每两个用相同颜色画的字母是不同的;
3.用红色画的字母数等于用绿色画的字母数;
4.在满足前三个条件的字符串的所有颜色中,这种颜色的着色字母的数量是最大的。
思路:因为一种字母只能染两种不同颜色,所以答案就是出现次数>=2的字母+只出现过一次的字母,两种情况相加即可
代码
#include <bits/stdc++.h>
#define int long long
#define ios ios::sync_with_stdio(false); cin.tie(0);
#define pii pair<int, int>
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
inline void solve() {
string s; cin >> s;
map<char, int> cnt, vis;
for(int i = 0; i < s.size(); i++) {
cnt[s[i]]++; vis[s[i]] = 0;
}
int ans = 0, t = 0;
for(int i = 0; i < s.size(); i++) {
if(vis[s[i]] == 0) {
if(cnt[s[i]] >= 2) ans++;
else t++;
vis[s[i]] = 1;
}
}
ans += t / 2;
cout << ans << endl;
return ;
}
signed main() {
ios;
int t; cin >> t;
while(t--) solve();
return 0;
}
B2 - Wonderful Coloring - 2
题意:用k种颜色对n个数字进行染色,要求满足以下条件:
1.序列中的每个元素要么是用k种颜色绘制的,要么是没有绘制的;
2.每两个被涂成同一颜色的元素是不同的。没有两个相同颜色的值);
3.让我们计算k种颜色中每一种颜色中绘制的元素的数量-所有计算的数字必须相等;
4.在满足前三个条件的序列的所有着色中,该序列的着色元素总数最大。
思路:
1.为了满足不重复染色,就将每个数字的前k个出现位置存起来
2.为了满足每个颜色染的数字数量都相同,那么总共的染色次数一定是k的整数倍
3.将保存的数字出现位置按照数字的大小从小到大排序,再每k个数字一循环染色即可
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline void solve() {
int n, k; cin >> n >> k;
vector<int> x(n), cnt(n + 10), q, ans(n);
for(int i = 0; i < n; i++) {
cin >> x[i];
cnt[x[i]]++;
if(cnt[x[i]] <= k) q.push_back(i);
}
while(q.size() % k != 0) q.pop_back();
sort(q.begin(), q.end(), [&](int i, int j) {return x[i] < x[j];});
for(int i = 0; i < q.size(); i++) {
ans[q[i]] = i % k + 1;
}
for(int i = 0; i < n; i++) cout << ans[i] << " ";
puts("");
return ;
}
signed main() {
ios::sync_with_stdio(false); cin.tie(0);
int t; cin >> t;
while(t--) solve();
return 0;
}
C - Interesting Story
题意:给定n个只由a, b,c,d,e组成的单词,判断最多选择多少个单词满足有一个字母出现的次数比其它字母出现的次数还要多
思路:由于只有5个字母,所以直接枚举5个字母在n个单词中的贡献即可,最后按照贡献从大到小排序。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline void solve() {
int n, ans = 0; cin >> n;
vector<string> s(n);
for(int i = 0; i < n; i++) cin >> s[i];
for(int i = 0; i < 5; i++) {
vector<int> f(n);
for(int j = 0; j < n; j++) {
for(auto u : s[j]) {
if(u == 'a' + i) f[j]++;
else f[j]--;
}
}
sort(f.begin(), f.end(), [&](int x, int y) {return x > y;} );
int sum = 0;
for(int i = 0; i < n; i++) {
sum += f[i];
if(sum <= 0) break;
ans = max(ans, i + 1);
}
}
cout << ans << endl;
return ;
}
signed main() {
int t; cin >> t;
while(t--) solve();
return 0;
}
D1 - Domino (easy version)
题意:给定一个包含nm个格子的棋盘,满足nm是偶数,并且两个相邻的未被使用的格子可以组成一个多米诺骨牌,只有竖直和水平两个方向,判断在满足所有格子都被使用的基础上,能否使得只有k个骨牌是水平放置的,其余骨牌是竖直放置的。
思路:首先判断对于该棋盘,所以构成的水平多米诺骨牌的最值,如果k不在这个范围内,那么肯定不满足条件,否则,由于使一个竖直放置得多米诺骨牌改变为水平放置,需要改变的是一个2*2的正方形区域,因此放置的水平多米诺骨牌数的所有可能情况具有相同的奇偶性,依据这个判断即可。
D2 - Domino (hard version)
思路:在D1判断出能否构造的基础上,我们考虑以下这种构造方法,如果是奇数行,那么将最后一行全部水平放置,否则不变化,之后将剩余部分全都竖直放置,之后如果水平多米诺骨牌不够,便按照2*2的正方形区域进行改变,这里注意由于我们是从头向右下角改变的,所以不会出现多改变的情况,并且这里注意运用到将二维下标转换为一维,以便保证编号不会重复的方法!
D1\D2代码如下
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline char get(int x, int y) {
x = x % 5;
y = y % 5;
return 'a' + x * 5 + y;
}
inline void solve() {
int n, m, k; cin >> n >> m >> k;
int MIN = (n % 2 == 1) ? m / 2 : 0;
int MAX = n * m / 2 - (m % 2 == 1 ? n / 2 : 0);
// cout << MAX << endl;
if(MIN <= k && k <= MAX && (k - MIN) % 2 == 0) {
cout << "YES" << endl;
vector<string> s(n, string(m, '?'));
if(n & 1) {
for(int i = 0; i < m; i += 2) {
s[n - 1][i] = s[n - 1][i + 1] = get(n - 1, i);
}
k -= MIN;
}
for(int i = 0; i < n - 1; i += 2) {
for(int j = 0; j < m; j++) {
s[i][j] = s[i + 1][j] = get(i, j);
}
}
for(int j = 0; j < m; j += 2) {
for(int i = 0; i < n - 1; i += 2) {
if(k > 0) {
s[i][j] = s[i][j + 1] = get(i, j);
s[i + 1][j] = s[i + 1][j + 1] = get(i + 1, j);
k -= 2;
}
}
}
for(int i = 0; i < n; i++) {
// for(int j = 0; j < m; j++)
// cout << s[i][j];
cout << s[i] << endl;
}
}
else {
puts("NO");
}
return ;
}
signed main(){
int t; cin >> t;
while(t--) solve();
return 0;
}