cf掉分日记-Educational Codeforces Round 123 (Rated for Div. 2) A - D
A - Doors and Keys
题目大意:
给三个钥匙用三个小写字母 r, g, b 表示,再给出三扇门 R, G, B ,问你顺序走过去,是否能开每一扇门。即所有字母都满足小写的在大写前面即可。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
#define endl '\n'
using namespace std;
const int N=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;
int a[N];
int main (){
IOS
int t; cin >> t;
while (t --){
string s; cin >> s;
int r, g, b, R, G, B;
for (int i = 0; i < 6 ; i ++){
if (s[i] == 'r') r = i;
else if (s[i] == 'R') R = i;
else if (s[i] == 'g') g = i;
else if (s[i] == 'G') G = i;
else if (s[i] == 'b') b = i;
else B = i;
}
if (r < R && g < G && b < B){
cout << "YES" << endl;
}
else cout << "NO" << endl;
}
return 0;
}
B - Anti-Fibonacci Permutation
题目大意:
输入 n,输出 满足 \(a[i - 1] + a[i - 2] != a[i]\) (3 <= i <= n),的 n 个长度为 n 的排列。
分析:
一开始急于求成了,直接暴力next_permutation() , 然后 暴力check t了。后来想想大概是个构造吧, 从最简单的开始想,逆序肯定是满足题意的, 如 5 4 3 2 1,然后发现交换其中相邻的两项依旧是满足的。swap 出了 n - 1 种,加上初始的一种刚好 n 种,然后没细想就上了,可能有更优的构造吧。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
#define endl '\n'
using namespace std;
const int N=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;
int a[N];
int main (){
IOS
int t; cin >> t;
while (t --){
int n; cin >> n;
for (int i = 1 ; i <= n ; i ++) a[i] = n + 1 - i;
for (int i = 1 ; i <= n ; i ++){
cout << a[i] << ' ';
}
cout << endl;
for (int i = 1 ; i < n ; i ++){
swap (a[i], a[i + 1]);
for (int j = 1 ; j <= n ; j ++){
cout << a[j] << ' ';
}
cout << endl;
swap (a[i], a[i + 1]);
}
}
return 0;
}
C - Increase Subarray Sums
题目大意:
如题名,最大连续子串和。经典问题了,本题的变式是,可以做 k 次操作,每次操作可以选择任意个位置加上 x,令 f(k) 等于k次操作最大连续子串和的可能最大值。求 \(f(0)\) 到 \(f(n)\) 。
分析:
赛中一开始走了很多弯路,一开始以为这是一个递推的过程,显然 \(f(1)\) 是可以 由 \(f(0)\) 直接推出来,但是 \(f(n)\) 选择加上x的点可能和 \(f(n - 1)\) 完全不一样的
10 3
-100 -100 1 1 1 -100 0 1 1 0
在上面这个样例中, \(f(3)\) 是选择 [1, 1, 1] 这一段加上3 ,结果为 12, 但是 \(f(4)\) 是选择 [0, 1, 1, 0] 一段,结果是 14。由此可以看出,选法并不能递推。这是我思考过程中的一个误区。
从上面跳出来之后,我很快就发现了正解。给一个区间的所有数加上某个值,使得这个区间变成最大的区间,那这个区间在同长度的区间中本身就是最大的了。于是用 \(n^2\) 的时间枚举区间,找到某一长度区间的最大值,记作 dp[i],表示长度为 i 的区间的最大值。那么对于 k 次操作,我们就可以更新 dp数组,使其中的数字加上 \(min (i, k) * x\) ,然后取更新后的数组的最大值就是答案。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
#define endl '\n'
using namespace std;
const int N=1e5+7;
const double eps=1e-6;
const int mod=1e9+7;
int a[N], q[N], dp[N], dp2[N];
int main (){
IOS
int t; cin >> t;
while (t --){
int n, x; cin >> n >> x;
for (int i = 1 ; i <= n ; i ++){
cin >> a[i];
q[i] = q[i - 1] + a[i];
dp[i] = -1e9;
}
for (int i = 1 ; i <= n ; i ++){
for (int j = 1 ; j + i - 1 <= n ; j ++){
int l = j, r = i + j - 1;
dp[i] = max(q[r] - q[l - 1], dp[i]);
}
}
for (int k = 0 ; k <= n ; k ++){
for (int i = 1 ; i <= n ; i ++){
dp2[i] = dp[i] + min (k, i) * x;
}
int maxn = 0;
for (int i = 1 ; i <= n ; i ++){
maxn = max (dp2[i], maxn);
}
cout << maxn << ' ';
}
cout << endl;
}
return 0;
}
D- Cross Coloring
题目大意:
给一个 n * m 的网格,有 k 种颜色,q 次操作, 每次操作选择一个点,在点所在行列都染成你所选的颜色。每次操作都可以从 k 种颜色中选一种。问在 q 次操作后,存在多少种不同颜色的表格。
分析:
做到这题的时候相当于背水一战了,成了就上蓝了,寄了就掉大分了
一开始没啥思路先去看的 e,感觉 e 更难写,就回过头来看看 d。其实挺简单的,只需要看所有操作后,表格中存在多少种色块就行,记为 c,(先假设每次涂的颜色都不一样)。答案就是 \(k ^ c\) 。
要注意的是题目只保证了 \(\sum q <= 2e5\) ,没有保证 n 和 m 的,每次清空长度为 n, m会很慢。理论上每次清空长度 n, m 要跑 2e9 次。但是 cf 神机貌似跑过去了。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
#define endl '\n'
using namespace std;
const int N=1e6+7;
const double eps=1e-6;
const int mod = 998244353;
bool x[N], y[N];
typedef pair <int, int> pii;
ll qpow(ll base, ll power) {
ll result = 1;
while (power > 0) {
if (power & 1) {
result = result * base % mod;
}
power >>= 1;
base = (base * base) % mod;
}
return result;
}
int main (){
IOS
int t; cin >> t;
while (t --){
ll n, m, k, q, cnt = 0; cin >> n >> m >> k >> q;
for (int i = 1 ; i <= n ; i ++){
x[i] = 0;
}
for (int i = 1 ; i <= m ; i ++){
y[i] = 0;
}
vector<pii> a;
while (q --){
int u, v;
cin >> u >> v;
a.push_back({u, v});
}
for (int i = a.size () - 1 ; i >= 0 ; i --){
if (!x[a[i].x] || !y[a[i].y]){
if (!x[a[i].x]){
x[a[i].x] = 1;
n --;
}
if (!y[a[i].y]){
y[a[i].y] = 1;
m --;
}
cnt ++;
if (!n || !m) break;
}
}
// cout << cnt << endl;
cout << qpow(k, cnt) << endl;
}
return 0;
}