Codeforces Round 958 (Div. 2)
2024-07-17 —yimg
A
簽到題
程式碼:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void work()
{
int n, k;
cin >> n >> k;
cout << (n - 1 + k - 2) / (k - 1) << '\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--)
work();
}
B
簽到題
程式碼:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void work()
{
int n; string s;
cin >> n >> s;
int c1 = 0, c0 = 0;
for(int i = 0; i < n; ++i){
if(s[i] == '1') c1++;
else if(s[i] == '0' && (i && s[i - 1] != '0' || !i) ) c0++;
}
cout << (c1 > c0 ? "YES" : "NO") << '\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--)
work();
}
C
題意:
給定正整數n, 求最長序列a,a需要滿足
-
\(a_i\le n\) , \(1\le i\le k\).
-
\(a_i>a_{i-1}\) , \(2\le i\le k\).
-
\(a_i\,|\,a_{i-1}=n\) , \(2\le i\le k\)
思路:
首先根據相鄰兩位按位or為n,我們可以忽略對構造答案沒有影響的0位, 接下來對\(2^{num(1)}-1\) 進行操作,\(a_k\)一定為\(2^{num(1)}-1\) , 貪心的想 : \(a_{k-1}\) 為小於\(a_k\) 的符合要求的最大值 , 即\(2^{num(1)}-1-2^0\) ,我們可以據此構造出num(1) + 1個答案。
實現上,依次刪去最高位就能得到答案。
程式碼:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void work()
{
ll n;
cin >> n;
vector<int> p;
ll a = 0, pre = 0;
for(ll i = 0, tmp = n; tmp; tmp >>= 1, ++i){
if(tmp&1){
a++;
p.push_back(i);
}
}
if(a == 1) cout << 1 << "\n";
else cout << a + 1 << '\n';
for(ll i = a - 1; a > 1 && i >= 0; --i){
ll res = n - (1ll << p[i]);
cout << res << " ";
}
cout << n;
cout << '\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--)
work();
D
題意:
有一顆n個節點的數,每個節點上都有一個攻擊力為\(a_i\)怪物,怪物每回合開始時結算一次攻擊,每個回合中可以進行操作,消滅任意只指定怪物,但是不能消滅相鄰兩個節點的怪物,問受到的攻擊值之和最小為多少。
思路:
選擇在第k回合消滅攻擊力為\(a_i\) 的怪物需要受到攻擊\(ka_i\) , 衝突的情況只有相鄰節點有影響,考慮用動態規劃解決。對於整個問題,回合數最多為\(\lceil log(n) \rceil\) (這個上限不知道怎麼證明)。
令\(f_{u,i}\) 為以u為根節點的子樹,選擇回合i時的最小值。記錄子節點的最小值和次小值,進行狀態轉移即可。複雜度為\(O(nlog_n)\)
程式碼:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void work()
{
int n;
cin >> n;
vector<ll> a(n + 1);
vector<vector<ll>> g(n + 1);
for(int i = 1; i <= n; ++i)
cin >> a[i];
for(int i = 1; i < n; ++i){
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
int lgn = __lg(n) + 1;
vector<vector<ll>> f(n + 1, vector<ll>(lgn + 1));
auto dfs = [&](auto &&self, int u, int p) -> void{
for(int i = 1; i <= lgn; ++i)
f[u][i] = a[u] * i;
for(auto v : g[u]){
if(v == p) continue;
self(self, v, u);
ll minn = 1e18, lm = 1e18, id = 0;
for(int i = 1; i <= lgn; ++i){
if(f[v][i] < lm){
lm = f[v][i];
if(lm < minn){
id = i;
swap(lm, minn);
}
}
}
for(int i = 1; i <= lgn; ++i){
if(i == id) f[u][i] += lm;
else f[u][i] += minn;
}
}
};
dfs(dfs, 1, -1);
ll minn = 1e18;
for(int i = 1; i <= lgn; ++i) minn = min(minn, f[1][i]);
cout << minn << "\n";
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--)
work();
}