Codeforces Round #638 (Div. 2)
A. Phoenix and Balance
将21,22,...,2n分成数量相等的两堆,使两堆和的差值最小
数据也不大,挺简单的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) int t, n; ll cnt[40]; int main() { cnt[1] = 2; rep(i, 2, 30) cnt[i] = cnt[i - 1] * 2; cin >> t; while (t--) { cin >> n; ll cnt1 = 0, cnt2 = 0, ans1 = 0, ans2 = 0; for (int i = n; i; i--) { if ((ans1 <= ans2 && cnt1 < n / 2) || cnt2 == n / 2) { cnt1++; ans1 += cnt[i]; } else { cnt2++; ans2 += cnt[i]; } } cout << abs(ans1 - ans2) << endl; } }
B. Phoenix and Beauty
通过在原数组插值构建beautiful array。
题目一直在强调不需要最小化m。可以构造一个长度为k的数组,输出n次,不成立的情况是原数组的数的种类大于k。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) int t, k, n, a[110]; int vis[110], cnt; int main() { cin >> t; while (t--) { cin >> n >> k; cnt = 0; rep(i, 1, n) vis[i] = 0; rep(i, 1, n) { cin >> a[i]; if (!vis[a[i]]) { vis[a[i]] = 1; cnt++; } } if (cnt > k) puts("-1"); else { cout << k * n << endl; rep(i, 1, n) { rep(j, 1, n) if (vis[j]) cout << j << " "; for (int j = 1, id = 1; id <= k - cnt; j++) if (!vis[j]) { id++; cout << j << " "; } } cout << endl; } } }
C题卡住了
D. Phoenix and Science
第一天有1团1个细菌,每团细菌每一天可能分裂为一半,也有可能不分裂。每团细菌每晚上+1个细菌,求细菌总数到达n的最小天数,还要写出分裂情况。
先计算天数。
设weight[0]=1,weight[1]=2,weight[2]=4... 为每天细菌的团数,那么Σ(1,x)weight[i]即为到达第x天时细菌总数,找到第一个使前缀和大于等于n的i
求得天数d为log2(n+1)-1向上取整。(其实具体计算没必要)
然后考虑每天的变化,变化就是weight数组的差分
在满足weight[i]∈(weight[i-1],weight[i-1]*2)的情况下适当减小就可以了
因为Σ(1,d-1)weight[i]<n,所以Σ(1,d)weight[i]-n>Σ(1,d-1)weight[i]
我们可以从第x天开始倒着减小weight[i-1]的值直到满足条件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for (register int i = a; i <= b; i++) ll t, n; ll mi[40]; ll d, weight[40]; int main() { mi[0] = 1; for (int i = 1; i <= 30; i++) { mi[i] = mi[i - 1] * 2; if (mi[i] >= 1e9) break; } cin >> t; while (t--) { cin >> n; if (n == 1) { puts("1\n0"); continue; } for (d = 0;; d++) { weight[d] = mi[d]; if (mi[d + 1] - 1 >= n) break; } ll dec = mi[d + 1] - 1 - n; for (int i = d;; i--) { if (weight[i - 1] < dec) { weight[i] -= weight[i - 1]; dec -= weight[i - 1]; } else { weight[i] -= dec; break; } } cout << d << endl; rep(i, 1, d) cout << weight[i] - weight[i - 1] << " "; cout << endl; } }