A, B题不多说
C题:
题意:给你n个相邻的木板, 每个木板宽度为1, 高度为ai,给你一把刷子, 每一次能刷宽度为1的连续的木板, 问最少刷几次能使全部木板换一种颜色
分析:答案最大为n, 就是每次都竖着刷, 若存在先横着刷的情况 则一定是把n个木板中最小的高度全部刷掉, 这样相当于每个木板的高度减去最小高度后需要的次数, 加上最小木板的高度, 递归求解
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, a[5010];
int dfs(int l, int r) {
int res = 0;
int min_v = 1 << 30;
for(int i=l; i<=r; i++) min_v = min(min_v, a[i]);
for(int i=l; i<=r; i++) a[i] -= min_v;
res += min_v;
for(int i=l; i<=r; i++) if(a[i]) {
for(int j=i; j<=r; j++) {
if(a[j] == 0) {
res += dfs(i, j-1);
i = j;
break;
}
else if(a[j] && j == r) {
res += dfs(i, j);
i = j;
break;
}
}
}
return min(res, r-l+1);
}
int main() {
scanf("%d", &n);
for(int i=1; i<=n; i++) scanf("%d", &a[i]);
printf("%d\n", dfs(1, n));
return 0;
}
D题:
题意:给你一个n*m的矩阵, i, j位子的大小为i*j, 求第k小的数
分析:二分求解,一开始最小值为1, 最大值为n*m,二分球的mid = (n + m) >> 1, 求小于等于Mid的数
for(int i=1; i<=n; i++) res += min(m, mid / n), 不过感觉还是有问题, 难道不会最后二分球的一个不存在的值满足条件吗, 虽然一直没有找到反例
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int n, m;
ll k;
ll f(ll x) {
ll res = 0;
for(int i=1; i<=n; i++)
res += min((ll)m, x / i);
return res;
}
int main() {
cin >> n >> m >> k;
ll l = 1, r = (ll)n * m;
ll ans = -1;
while(l <= r) {
ll mid = (l + r) >> 1;
if(f(mid) >= k) {
ans = mid;
r = mid - 1;
}
else
l = mid + 1;
}
printf("%I64d\n", ans);
return 0;
}
E题:
题意:给你x, k, f()是每一数的因子的递增排列, xi = f(x i -1), 求x(k);
分析:dfs递归求解, 搜索的过程就像一颗搜索树
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
ll a[1000010], x, k;
ll sum, tot;
vector <ll> div1[111111];
void dfs(ll cnt, ll cur) {
if(sum >= 100000) return;
if(cnt == 1) {
printf("1 ");
sum++;
return;
}
if(cur == 0) {
printf("%I64d ", a[cnt]);
sum++;
return;
}
for(ll i=0; i<div1[cnt].size(); i++) {
dfs(div1[cnt][i], cur - 1);
if(sum >= 100000) return;
}
}
int main() {
cin >> x >> k;
sum = 0;
tot = 0;
for(ll i=1; i*i <= x; i++) if(x % i == 0) {
a[++tot] = i;
if(i*i != x) a[++tot] = x / i;
}
sort(a+1, a+tot+1);
for(ll i=1; i<=tot; i++)
for(ll j=1; j<=i; j++) if(a[i] % a[j] == 0)
div1[i].push_back(j);
dfs(tot, k);
return 0;
}