題目連結:Codeforces Round 957 (Div. 3)
總結:E不懂,F差一個set去重
A. Only Pluses
fag:列舉
B. Angry Monk
fag:模擬
Solution:分裂的花費為\(a_i - 1\),新增的花費為\(a_i\)。
C. Gorilla and Permutation
fag:思維
Solution:大於等於\(k\)的數,逆序放在最前面,小於等於\(m\)的數,從最後面開始從大到小放,中間的位置任意放剩下的數。
void solve(){
cin >> n >> m >> k;
vector<int> a(n + 1);
int i, l, r;
for (i = n, l = 1; i >= k; i --, l ++)
a[l] = i;
for (i = m, r = n; i >= 1; i --, r --)
a[r] = i;
for (int i = l; i <= r; i ++){
a[i] = ++ m;
}
for (int i = 1; i <= n; i ++)
cout << a[i] << " \n"[i == n];
}
D. Test of Love
fag:DP
Solution:考慮如何從上一步轉移,跳過來或者游過來。
- 注意\(m\)的範圍,可以直接列舉前\(m\)個格子(賽時沒看到範圍,用單調佇列最佳化DP做的)
- 游過來的前提,上一格是水。
void solve(){
cin >> n >> m >> k;
string s;
cin >> s;
s = "$" + s;
deque<int> qu;
vector<int> f(n + 2, INF);
f[0] = 0;
qu.push_back(0);
for (int i = 1; i <= n + 1; i ++){
if (s[i] == 'C')
continue;
while (qu.size() && qu.front() + m < i){ // 儲存原木的座標
qu.pop_front();
}
if (qu.size())
f[i] = f[qu.front()];
if (s[i - 1] == 'W')
f[i] = min(f[i], f[i - 1] + 1);
if (s[i] == 'L'){
while (qu.size() && f[qu.back()] >= f[i])
qu.pop_back();
qu.push_back(i);
}
}
if (f[n + 1] > k){
cout << "NO\n";
}
else{
cout << "YES\n";
}
}
E. Novice's Mistake
fag:思維
Desription:給定一個\(n\),求出所有滿足條件的\(a, b\)組合。
- \(1 <= a <= 1e4, 1 <= n <= 100\)
- \(n * a - b\)等於將\(a\)個字串\(n\)然後刪去末尾\(b\)個字元之後代表的整數
- \(n * a - b > 0\)
Solution:注意到字串的操作會影響答案的位數,但是數值計算\(n * a\)最多為\(1e6\)所以最大隻有\(6\)位。
- 我們列舉\(a\),然後列舉答案的位數\(k\),對於每個\(k\)求出一個\(b\),判斷當前\(a, b\)是否滿足條件
Competing:賽場根本沒想到位數的關係
void solve(){
string n;
cin >> n;
vector<pii> ans;
for (int a = 1; a <= 10000; a ++){
int len = to_string(stoi(n) * a).size(); // 當前位數
// if (a == 1262)
// debug(len);
for (int k = len; k; k --){
int b = a * n.size() - k;
if (!b)
continue;
int t = 0;
for (int i = 1, j = 0; i <= k; i ++){
if (j == n.size())
j = 0;
t = t * 10 + (n[j ++] - '0');
}
if (t == stoi(n) * a - b){
ans.push_back({a, b});
}
// if (a == 1262 && b == 2519){
// debug(t, stoi(n) * a - b);
// }
}
}
cout << ans.size() << endl;
for (auto [a, b] : ans){
cout << a << " " << b << endl;
}
}
F. Test of Love
fag:思維
Description:有\(n\)個數,給定一個\(x\),將\(n\)個數分為\(k\)個連續區間,每個區間滿足任意一個子集的乘積不等於\(x\)。
1 <= n <= 1e5 2 <= x <= 1e5
1 <= a_i <= 2e5
Solution:從前往後模擬當前區間能夠得到那些因數(使用set去重),因為因數的個數很少,所以可做
Competing:沒考慮到使用\(set\)去重
void solve(){
int x;
cin >> n >> x;
vector<int> a(n);
set<int> v; // 記錄當前區間所有可能出現的x的約數
for (int i = 0; i < n; i ++)
cin >> a[i];
int ans = 1;
for (int i = 0; i < n; i ++){
if (x % a[i])
continue;
set<int> tmp;
for (auto j : v){
tmp.ep(a[i] * j); // 記錄能夠構造出來的數
}
for (auto j : tmp){
if (x % j)
continue;
v.ep(j);
}
if (v.find(x) != v.end()){
ans ++;
v.clear();
}
v.ep(a[i]);
}
cout << ans << endl;
}