A. Definite Game
签.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int a; 7 while (scanf("%d", &a) != EOF) 8 { 9 [](int x) 10 { 11 for (int i = x - 1; i >= 1; --i) if (x % i) 12 { 13 printf("%d ", x - i); 14 return; 15 } 16 printf("%d ", x); 17 }(a); 18 } 19 return 0; 20 }
B. Farewell Party
签。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, a[N], b[N], cnt[N]; 6 vector <int> v[N]; 7 int ans[N]; 8 9 bool ok() 10 { 11 for (int i = 1; i <= n; ++i) if (!v[i].empty() && v[i].size() != i) 12 return false; 13 return true; 14 } 15 void solve() 16 { 17 int cnt = 0; 18 for (int i = 1; i <= n; ++i) v[i].clear(); 19 for (int i = 1; i <= n; ++i) 20 { 21 int id = n - a[i]; 22 if (v[id].size() == id) 23 { 24 ++cnt; 25 for (auto it : v[id]) ans[it] = cnt; 26 v[id].clear(); 27 } 28 v[id].push_back(i); 29 } 30 if (!ok()) 31 { 32 puts("Impossible"); 33 return; 34 } 35 else 36 { 37 for (int i = 1; i <= n; ++i) if (!v[i].empty()) 38 { 39 ++cnt; 40 for (auto it : v[i]) 41 ans[it] = cnt; 42 } 43 puts("Possible"); 44 for (int i = 1; i <= n; ++i) printf("%d%c", ans[i], " "[i == n]); 45 } 46 } 47 48 int main() 49 { 50 while (scanf("%d", &n) != EOF) 51 { 52 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 53 solve(); 54 } 55 return 0; 56 }
C. Colorful Bricks
Upsolved.
题意:
有$一行n个方格,m种颜色,恰好有k个方块与它左边方块的颜色不同$
求方案数
思路:
$dp[i][j] 表示到第i个方格,有j个方块与左边方块颜色不同的方案数$
转移有
$dp[i + 1][j] += dp[i][j]$
$dp[i + 1][j + 1] += dp[i][j] * (m - 1)$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 2010 6 const ll MOD = (ll)998244353; 7 int n, m, k; 8 ll f[N][N]; 9 10 int main() 11 { 12 while (scanf("%d%d%d", &n, &m, &k) != EOF) 13 { 14 memset(f, 0, sizeof f); 15 f[1][0] = m; 16 for (int i = 2; i <= n; ++i) 17 { 18 for (int j = 0; j <= min(i - 2, k); ++j) 19 { 20 f[i][j] = (f[i][j] + f[i - 1][j]) % MOD; 21 f[i][j + 1] = (f[i][j + 1] + f[i - 1][j] * (m - 1) % MOD) % MOD; 22 } 23 } 24 printf("%lld ", f[n][k]); 25 } 26 return 0; 27 }
D. Maximum Distance
Upsolved.
题意:
有一张图
定义一条路径的长度的路径上边权最大值
定义两点距离为两点之间最短路径
有一些特殊点,要对所有特殊点求离它最远的特殊点
思路:
我们考虑一条边所连接的两个连通块里,如果这两个连通块里都有特殊点
那么这条边的权值就可以用于更新特殊点的答案
其实就是一个求最小生成树的过程,先按边权排序
要注意的是不是求整个图的最小生成树,而是所有特殊点的最小生成树
其实是最小瓶颈生成树.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, m, k; 6 struct node 7 { 8 int u, v, w; 9 void scan() { scanf("%d%d%d", &u, &v, &w); } 10 bool operator < (const node &other) const { return w < other.w; } 11 }edge[N]; 12 13 int pre[N], cnt[N]; 14 int find(int x) { return pre[x] == 0 ? x : pre[x] = find(pre[x]); } 15 int Kruskal() 16 { 17 sort(edge + 1, edge + 1 + m); 18 for (int i = 1; i <= m; ++i) 19 { 20 int u = edge[i].u, v = edge[i].v, w = edge[i].w; 21 int fu = find(u), fv = find(v); 22 if (fu == fv) continue; 23 cnt[fv] += cnt[fu]; 24 pre[fu] = fv; 25 if (cnt[fv] == k) return w; 26 } 27 } 28 29 int main() 30 { 31 while (scanf("%d%d%d", &n, &m, &k) != EOF) 32 { 33 memset(pre, 0, sizeof pre); 34 memset(cnt, 0, sizeof cnt); 35 for (int i = 1, x; i <= k; ++i) scanf("%d", &x), cnt[x] = 1; 36 for (int i = 1; i <= m; ++i) edge[i].scan(); 37 int res = Kruskal(); 38 for (int i = 1; i <= k; ++i) printf("%d%c", res, " "[i == k]); 39 } 40 return 0; 41 }
E. Missing Numbers
Upsolved.
题意:
有$n个数,给出a_2, a_4 cdots a_n$
$n是偶数,提供a_1, a_3 cdots a_{n - 1}$
使得
$所有前缀和都是平方数$
思路:
考虑$n = 2的时候$
$我们令b^2 = a_1 + a_2$
$a^2 = a_1$
那么有
$b^2 - a^2 = (b + a) cdot (b - a) = a_2$
$我们将a_2 拆成 p cdot q 的形式$
$令p >= q$
$那么有 b + a = p, b - a = q$
$解方程有 b = frac{p + q}{2}$
$发现一限制条件 p, q的奇偶性要相同$
$那么a_1 = (frac{p + q}{2})^2 - a_2$
那么如果有多解 我们取$a_1最小的$
$因为当n >= 2的情况也可以同样这样推下去,会发现前面的项越小越好$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 int n; 7 ll x[N]; 8 vector <int> vec[N << 1]; 9 10 void init() 11 { 12 for (int i = 1; i <= 450; ++i) 13 for (int j = i * i; j <= 200000; j += i) 14 vec[j].push_back(i); 15 } 16 17 int main() 18 { 19 init(); 20 while (scanf("%d", &n) != EOF) 21 { 22 for (int i = 2; i <= n; i += 2) scanf("%lld", x + i); 23 bool flag = true; 24 ll base = 0; 25 for (int i = 1; i <= n; i += 2) 26 { 27 base += x[i + 1]; 28 int limit = sqrt(x[i + 1]); 29 ll res = (ll)1e18; 30 ll p, q; 31 for (auto j : vec[x[i + 1]]) 32 if ((j % 2) == ((x[i + 1] / j) % 2)) 33 { 34 p = j, q = (x[i + 1] / j); 35 ll tot = (p + q) / 2; 36 tot *= tot; 37 if (tot > base) 38 res = min(res, tot - base); 39 } 40 if (res <= (ll)1e13) 41 { 42 x[i] = res; 43 base += res; 44 } 45 else 46 { 47 flag = false; 48 break; 49 } 50 } 51 if (!flag) puts("No"); 52 else 53 { 54 puts("Yes"); 55 for (int i = 1; i <= n; ++i) 56 printf("%lld%c", x[i], " "[i == n]); 57 } 58 } 59 return 0; 60 }