20230518 solution ( fbi + money + fruit )
T1
通过观察样例我们可以得知 每一个节点的字母类型与它所包含范围内的1 0 有关
只存在三种情况:全是1 全是0 有1有0
所以直接用前缀和判断即可 递归建树
记得开四倍空间
code :
#include <bits/stdc++.h>
#define ls (k << 1)
#define rs (k << 1 | 1)
#define mid ((l + r) >> 1)
using namespace std;
const int N = 1e5 + 0721;
int d[N];
string s;
int tr[N];
int n, len;
void def(int k, int l, int r) {
int sum = d[r] - d[l - 1];
if (l == r) {
if (sum == 0) tr[k] = 'B' - 'A';
else tr[k] = 'I' - 'A';
return;
}
if (sum == 0) tr[k] = 'B' - 'A';
else if (sum == r - l + 1) tr[k] = 'I' - 'A';
else tr[k] = 'F' - 'A';
}
void build(int k, int l, int r) {
def(k, l, r);
if (l == r) return;
build(ls, l, mid);
build(rs, mid + 1, r);
}
void print(int k) {
if (tr[ls] != 0) print(ls);
if (tr[rs] != 0) print(rs);
printf("%c",tr[k] + 'A');
}
int main() {
scanf("%d", &n);
len = (1 << n);
cin >> s;
for (int i = 1; i <= len; ++i) d[i] = d[i - 1] + s[i - 1] - '0';
build(1, 1, len);
print(1);
return 0;
}
T2
每个面值的硬币都可以拿无数个 考虑多重背包
要求方案数 想到从多重背包的思路考虑
分两种情况:
- 当前空间不够拿 \(f[i][j] = f[i][j - 1]\)
- 够拿 \(f[i][j] = f[i][j - 1] + f[i - c[i]][j]\)
注意初值:\(f[0][0] = 1\)
ans最大值我不会算 但是感觉是要开long long的
这题数据范围不大 同样可以二维数组摆烂
code :
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4 + 0721;
ll f[101][N];
int c[101];
int n, m;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= m; ++j) {
if (j < c[i]) f[i][j] = f[i - 1][j];
else f[i][j] = f[i - 1][j] + f[i][j - c[i]];
// cout << f[i][j] << " " ;
}
// cout << endl;
}
printf("%lld",f[n][m]);
return 0;
}
T3
经典哈夫曼堆 没啥可说的
code :
#include <bits/stdc++.h>
#define ll long long
using namespace std;
priority_queue<ll, vector<ll>, greater<ll> >q;
ll ans;
int n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
ll x;
scanf("%lld", &x);
q.push(x);
}
while (q.size() != 1) {
ll now1 = q.top();
q.pop();
ll now2 = q.top();
q.pop();
now1 += now2;
ans += now1;
q.push(now1);
}
printf("%lld",ans);
return 0;
}