A.Fill The Bag
Link
https://codeforces.com/contest/1303/problem/D
Statement
给定一个正整数 \(n\) 和 \(m\) 个数 \(a_i\),保证所有 \(a_i\) 都是 \(2\) 的整数次幂。询问是否存在一个长度为 \(m\) 的序列 \(x_i\),使得:
\[\sum _ {i = 1} ^ {m} \frac {a_i}{2 ^ {x_i}} = n \]且 \(\sum _{i = 1} ^ {m} x_i\) 最小。若存在则输出 \(\sum _{i = 1} ^ {m} x_i\) 。
Solution
由于 \(a_i\) 是 \(2\) 的整数次幂,则 \(\frac {a_i}{2 ^ {x_i}}\) 则可以看作是 \(n\) 的二进制表示。原问题可以转化为:是否可以通过已有的一些个 \(2\) 的整数次幂,“凑”出 \(n\) 的二进制表示。
大的数只能往小变,小的数可以拼凑成大的数。且由于要最小化 div
次数,我们可以按位从低到高考虑。假设当前即将考虑第 \(i\) 位,我们可以先试着用 \(i - 1\)位的来凑第 \(i\) 位的。若凑不出来,那就用 \(i\) 后面的有的最小的来凑 \(i\)。
Code
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1e5 + 5;
using namespace std;
int T, m, a[N];
ll n, cnt[100];
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
freopen("in","r", stdin);
cin >> T;
while (T--) {
cin >> n >> m;
ll sum = 0;
for (int i = 1; i <= m; i++) {
cin >> a[i];
sum += a[i];
int ex = log2(a[i]);
cnt[ex]++;
}
if (sum < n) cout << "-1" << endl;
else {
ll ans = 0;
for (int i = 0; i < 60; i++) {
if ((n >> i) & 1) {
int pos = i;
while (!cnt[pos]) ++pos;
--cnt[pos];
while (pos > i) {
--pos;
cnt[pos]++;
++ans;
}
}
cnt[i + 1] += cnt[i] / 2;
}
cout << ans << endl;
}
memset(cnt, 0, sizeof(cnt));
}
return 0;
}
B.Obtain The String
Link
https://codeforces.com/contest/1295/problem/C
Statement
给定两个字符串 \(s\) 与 \(t\),令 \(tt\) 为空串。定义一种操作:每次可以选择 \(s\) 的一个字串 \(ss\)(非连续也可以),并把 \(ss\) 加入 \(tt\) 的末尾。询问是否能使 \(tt = t\),若可以输出最小的操作次数。
Solution
定义 \(f_{i,c}\) 表示 \(s\) 中从 第 \(i\) 位开始的后缀串中字母 \(c\) 出现的最早位置。 从后往前扫一遍即可得到这个 \(f\)。结合贪心的思想,每一次新的操作从第一位往后跳即可,跳到末尾则进行下一次操作。
Code
#include <bits/stdc++.h>
const int INF = 1 << 30;
const int N = 2e5 + 5;
using namespace std;
int T, g[N][30];
char s[N], t[N];
set<char> ss;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
freopen("in","r", stdin);
cin >> T;
while (T--) {
cin >> (s + 1) >> (t + 1);
int lens = strlen(s + 1), lent = strlen(t + 1);
for (int i = 1; i <= lens; i++) ss.insert(s[i]);
bool flag = false;
for (int i = 1; i <= lent; i++) {
if (!ss.count(t[i])) {
flag = true;
break;
}
}
ss.clear();
if (flag) cout << "-1" << endl;
else {
for (int j = 1; j <= 26; j++) g[lens + 1][j] = INF;
for (int i = lens; i >= 1; i--) {
for (int j = 1; j <= 26; j++) g[i][j] = g[i + 1][j];
g[i][s[i] - 'a' + 1] = i;
}
int pos = 1, now = 1, cnt = 0;
bool sign = false;
while (now <= lent) {
if (g[pos][t[now] - 'a' + 1] == INF) {
cnt++;
pos = 1;
sign = false;
}
else pos = g[pos][t[now] - 'a' + 1] + 1, now++, sign = true;
if (pos == lens + 1) {
cnt++;
pos = 1;
sign = false;
}
}
if (sign) cnt++;
cout << cnt << endl;
}
}
return 0;
}
标签:cnt,cin,int,sum,13,pos,--,2023.1
From: https://www.cnblogs.com/BeyondLimits/p/17051056.html