A
可知把最大的分配給a,從大到小分配n/2個元素給b,其餘給a
int t; cin >> t;
while (t--)
{
int n; cin >> n;
ll ans1 = 0, ans2 = 0;
ans1 = 1 << n;
for (int i = n - 1; i >= n - n / 2; --i) {
ans2 += 1 << i;
}
for (int i = n - n / 2 - 1; i >= 1; --i) {
ans1 += 1 << i;
}
cout << ans1 - ans2 << endl;
}
B
構成循環節,分析可得出現數字種類多於k將無法構造
按照出現的數字,在原序列中補充即可
int a[maxn], vis[105];
vector<int> ans, pre;
int main()
{
int t; scanf("%d", &t);
while (t--) {
int n, k; scanf("%d%d", &n, &k);
memset(vis, 0, sizeof(vis)); pre.clear();
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
if (vis[a[i]]++ == 0) {
pre.push_back(a[i]);
}
}
if (pre.size() > k) {
printf("-1\n");
continue;
}
if (n == 1) {
printf("1\n1\n");
continue;
}
while (pre.size() < k) pre.push_back(1);
sort(pre.begin(), pre.end());
ans.clear();
for (int i = 1, last; i <= n; ++i) {
if (i == 1) {
for (int j = 0; j < k; ++j) {
ans.push_back(pre[j]);
if (pre[j] == a[i]) {
last = j + 1;
break;
}
}
}
else if (i != n) {
for (int j = last; j < k; ++j) {
ans.push_back(pre[j]);
}
for (int j = 0; j < k; ++j) {
ans.push_back(pre[j]);
if (pre[j] == a[i]) {
last = j + 1;
break;
}
}
}
else {
for (int j = last; j < k; ++j) {
ans.push_back(pre[j]);
}
for (int j = 0; j < k; ++j) {
ans.push_back(pre[j]);
}
}
}
printf("%d\n", ans.size());
for (int i = 0; i < ans.size(); ++i) {
if (i == ans.size() - 1) printf("%d\n", ans[i]);
else printf("%d ", ans[i]);
}
}
}
C
貪心,單個字符直接k個k個放置;兩種或多個字符,若最小種字符個數,輸出第k大的字符;兩種字符再特判一下,最小種字符正好k個,次小種按k個k個放置的情況;其餘情況,放置好前k個後直接全部排在一個字符後
char s[maxn];
map<int, int> mp;
vector< pair<int, int> >mpp;
int main()
{
int t; scanf("%d", &t);
while (t--) {
int n, k; scanf("%d%d", &n, &k);
scanf("%s", s); mp.clear(); mpp.clear();
for (int i = 0; i < n; ++i) {
mp[s[i] - 'a']++;
}
for (auto m : mp) {
mpp.push_back(m);
}
if (mpp.size() == 1) {
char ch = mpp[0].first + 'a';
int cnt = mpp[0].second;
int mul = cnt / k;
if (cnt % k == 0) {
for (int i = 0; i < mul; ++i) putchar(ch);
}
else for (int i = 0; i <= mul; ++i) putchar(ch);
putchar('\n');
}
else {
if (mpp[0].second < k) {
k -= mpp[0].second;
for (int i = 1; i < mpp.size(); ++i) {
if (mpp[i].second >= k) {
putchar(mpp[i].first + 'a');
putchar('\n');
break;
}
k -= mpp[i].second;
}
}
else if (mpp[0].second > k) {
putchar(mpp[0].first + 'a');
for (int i = 0; i < mpp[0].second - k; ++i) putchar(mpp[0].first + 'a');
for (int i = 1; i < mpp.size(); ++i) {
for (int j = 0; j < mpp[i].second; ++j)
putchar(mpp[i].first + 'a');
}
putchar('\n');
}
else {
if (mpp.size() == 2) {
putchar(mpp[0].first + 'a');
char ch = mpp[1].first + 'a';
int cnt = mpp[1].second;
int mul = cnt / k;
if (cnt % k == 0) for (int i = 0; i < mul; ++i) putchar(ch);
else for (int i = 0; i <= mul; ++i) putchar(ch);
putchar('\n');
}
else {
putchar(mpp[0].first + 'a');
for (int i = 1; i < mpp.size(); ++i) {
for (int j = 0; j < mpp[i].second; ++j)
putchar(mpp[i].first + 'a');
}
putchar('\n');
}
}
}
}
}
D
分析題意,根據分裂關係可得下個時間數量爲 [該時間數量,該時間數量x2]之間;並且總數量是前綴和關係,因此我們需要計算的就是,其中k最小,
直接按構造序列,使前綴和,若sum不足補上n-sum在排序
答案即是 構造序列的差分序列
int t; scanf("%d", &t);
while (t--) {
int n; scanf("%d", &n);
int sum = 0; a.clear();
for (int i = 0; ; ++i) {
if (1ll * sum + (1 << i) > n) break;
sum += 1 << i;
a.push_back(1 << i);
}
if (n != sum) a.push_back(n - sum);
sort(a.begin(), a.end());
printf("%d\n", a.size() - 1);
for (int i = 1; i < a.size(); ++i) {
printf("%d ", a[i] - a[i - 1]);
}
printf("\n");
}
E
看了很久還是不是很會,哭了