A. Bear and Big Brother(Codeforces 791A)
思路
由於
代碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, b, x, y;
int main() {
// freopen("Input3.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cin >> a >> b;
x = 1;
y = 1;
for(int i = 1; i <= 20; i++) {
x *= 3;
y *= 2;
if(a * x > b * y) {
cout << i << endl;
break;
}
}
return 0;
}
B. Bear and Friendship Condition(Codeforces 791B)
思路
這種有“關係”的題目,用圖來建模最合適不過。所以問題轉化爲每個連通分量的子圖是否構成“完全圖”,也就是兩點之間是否都有邊相連。完全圖有一個性質:其點數
代碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5;
vector <int> G[maxn];
bool vis[maxn];
int u, v, n, m;
ll V, E;
void dfs(int u) {
vis[u] = true;
E += G[u].size();
V++;
for(int v : G[u]) {
if(vis[v] == true) {
continue;
}
dfs(v);
}
}
int main() {
// freopen("Input1.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
while(m--) {
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++) {
if(vis[i] == true) {
continue;
}
V = E = 0;
dfs(i);
if(V * (V - 1) != E) {
puts("NO");
return 0;
}
}
puts("YES");
return 0;
}
C. Bear and Different Names(Codeforces 791C)
思路
本題只需要構造一組解。搜索的話複雜度太高,可以先考慮貪心的思想。首先應當明確,輸入中的一個字符串
例如
如果窗口的描述是
(注意,下面的構造方法以第一組樣例爲例)
- 先構造前
k−1 個元素。將其構造成升序即可。那麼我們構造出序列[1,2] 。 - 然後構造第
k 個元素。檢查第1 個字符串,如果其爲NO 則在序列末尾添加與其窗口起始元素相同的元素,如果其爲YES ,那麼添加新的元素即可。在第一組樣例中此時的序列變爲[1,2,1] 。 - 重複第
2 個步驟,即不斷往序列末尾添加新元素。序列依次被構造成 ->1,[2,1,2] ->1,2,[1,2,3] ->1,2,1,[2,3,4] ->1,2,1,2,[3,4,5] ->1,2,1,2,3,[4,5,4] - 最後序列被構造出來了,第一組樣例構造出的序列是
1,2,1,2,3,4,5,4 ,將數字映射到姓名即可。比如可以將數字看成26 進制數然後用英文字幕A,B,C …表示1,2,3 …(如下)。
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
string s[maxn];
int name[maxn];
int n, k, cnt;
int main() {
// freopen("Input1.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> k;
for(int i = k; i <= n; i++) {
cin >> s[i];
}
for(int i = 1; i <= k - 1; i++) {
name[i] = ++cnt;
}
for(int i = k; i <= n; i++) {
if(s[i] == "YES") {
name[i] = ++cnt;
}
else {
name[i] = name[i - k + 1];
}
}
for(int i = 1; i <= n; i++) {
cout << (char)(name[i] % 10 + 'A');
cout << (char)(name[i] / 10 + 'a') << ' ';
}
return 0;
}
D. Bear and Tree Jumps(Codeforces 791D)
思路
先將問題簡化爲
令
接着要將問題推廣到
也就是說
如果能求出
那麼我們需要對每條路徑算模
代碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5, maxk = 10;
vector <int> G[maxn];
int n, k, u, v;
ll ans, w[maxn], cnt[maxn][maxk];
int sub(int a, int b) {
return ((a - b) % k + k) % k;
}
// 邊搜索邊統計需要的數據
void dfs(int u, int p, int d) {
w[u] = cnt[u][d % k] = 1;
for(int v : G[u]) {
if(v == p) {
continue;
}
dfs(v, u, d + 1);
for(int i = 0; i < k; i++) {
for(int j = 0; j < k; j++) {
// r爲餘數,k爲還要多少能模k餘0
int r = sub(i + j, 2 * d);
int need = sub(k, r);
// 計算貢獻度
ans += need * cnt[u][i] * cnt[v][j];
}
}
// 從子樹總累加cnt[u][i]
for(int i = 0; i < k; i++) {
cnt[u][i] += cnt[v][i];
}
w[u] += w[v];
}
// 計算貢獻度
ans += w[u] * (n - w[u]);
}
int main() {
// freopen("Input2.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> k;
for(int i = 1; i <= n - 1; i++) {
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, -1, 0);
cout << ans / k << endl;
return 0;
}
(其它題目略)