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)\)
從上面跳出來之後,我很快就發現了正解。給一個區間的所有數加上某個值,使得這個區間變成最大的區間,那這個區間在同長度的區間中本身就是最大的了。於是用 \(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;
}