题目链接:
https://codeforces.com/contest/1656
D. K-good
题目大意:
一个数如果能被 \(k\) 个不同的数表示,同时这 \(k\) 个数 % \(k\) 之后的余数不同,那么它是 \(k - good\) 数。给定 \(n\),如果它是 \(k - good\) 数,则输出任意满足的 \(k\),否则输出 -1。
思路:
首先容易发现 \(n\) 可以表示为 \(\frac{k * (k + 1)}{2} + k * t(t = 0, 1, 2, ...)\)。
转化一下得到 \(2 * n = k * (k + 1 + 2 * t)\),\(k\) 和 \(k + 1 + 2 * t\) 的奇偶性不同,所以 \(2 * n\) 是由一个奇数和一个偶数相乘得到。
将 \(2 * n\) 分解一下,小的那个数就是 \(k\)。
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL T, n;
void solve(){
cin >> n;
LL a = n * 2, b = 1;
while (a % 2 == 0){
a /= 2;
b *= 2;
}
LL k = min(a, b);
cout << (k == 1 ? -1 : k) << "\n";
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin >> T;
while (T -- )
solve();
return 0;
}
E. Equal Tree Sums
题意:
给一棵树上的所有点进行赋值,要求删除任意一个节点后,剩下的连通块中所有点的权值之和相同。
思路:
将树进行黑白染色,黑色的点的权值为它的度数,白色的点的权值为它的度数的相反数。
这样子操作之后,不论移去哪一个点,它会将树分成它的度数个连通块,每个连通块少了它的贡献值,即变成 + 1,或者 - 1,也就是全部相等。
代码:
#include <bits/stdc++.h>
using namespace std;
int T, n;
void solve(){
cin >> n;
vector < vector <int> > g(n + 1);
for (int i = 0; i < n - 1; i ++ ){
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
vector < int > ans(n + 1);
function < void (int, int, int) > dfs = [&](int u, int p, int c){
ans[u] = c * (int)g[u].size();
for (auto v : g[u]){
if (v == p) continue;
dfs(v, u, -c);
}
};
dfs(1, 0, 1);
for (int i = 1; i <= n; i ++ )
cout << ans[i] << " \n"[i == n];
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin >> T;
while (T -- )
solve();
return 0;
}