codeforces-Edu-94
题解
文章目录
RPG Protagonist (暴力枚举)
题意:
两个容器 p
,f
,有单价为 s
的剑 cnts
把, 单价为 w
的斧头 cntw
把。
求最多能拿走多少把武器(只要是武器都算1
)
思路:
先保证 s < w
暴力枚举 p
中装的 s
的数量,剩下的装 w
。
然后 f
中贪心的拿武器,先拿 s
,再拿 w
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define eps 1e-9
#define INF 0x3f3f3f3f
#define pb push_back
#define mk make_pair
#define fi first
#define se second
using namespace std;
typedef unsigned int UI;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> P;
const int N = 1e5 + 10;
int p, f;
int cnts, cntw;
int s, w;
int main () {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &p, &f);
scanf("%d%d", &cnts, &cntw);
scanf("%d%d", &s, &w);
if (s > w) {
swap(s, w);
swap(cnts, cntw);
}
int ans = 0;
for (int i = 0; i <= cnts; i++) {
if (i * s > p) break;
int tmp = i; //p取i个s
int c1 = cnts - i; //当前的s
int c2 = cntw; //当前的w
int k = min(c2, (p - i * s) / w);
tmp += k; //p剩下的加w
c2 -= k; //w减少
int ff = f;
k = min(c1, ff / s);
ff -= k * s;
tmp += k;
k = min(c2, ff / w);
ff -= k * w;
tmp += k;
ans = max(ans, tmp);
}
printf("%d\n", ans);
}
return 0;
}
Binary String Reconstruction
题意:
。。。。。不想描述,直接看题
思路:
先根据得到的串中的 0
,确定原串中必为0
的位置
再根据 1
的位置,判断是否合法。
若为 1
,两边至少存在一个 1
,若有未确定的,并且没有1
, 则确定该格为 1
。
最后还存在 -1
(不确定的)就随便输出。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define eps 1e-9
#define INF 0x3f3f3f3f
#define pb push_back
#define mk make_pair
#define fi first
#define se second
using namespace std;
typedef unsigned int UI;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> P;
const int N = 1e5 + 10;
char s[N];
int main () {
int t;
scanf("%d", &t);
while (t--) {
scanf("%s", s + 1);
int n = strlen(s + 1);
int x;
scanf("%d", &x);
vector<int> ans(n + 1, -1);
for (int i = 1; i <= n; i++) {
if (s[i] == '0') {
if (i > x) ans[i - x] = 0;
if (i + x <= n) ans[i + x] = 0;
}
}
bool f = true;
for (int i = 1; i <= n; i++) {
if (s[i] == '1') {
if (i > x && i + x <= n) {
if (ans[i - x] == 0 && ans[i + x] == 0) {
f = false;
break;
}
else {
int k = ans[i - x] + ans[i + x];
if (k == -2) {
ans[i - x] = 1;
}
else if (k == -1) {
if (ans[i - x] == -1) ans[i - x] = 1;
else ans[i + x] = 1;
}
}
}
else if (i > x) {
if (ans[i - x] == 0) {
f = false;
break;
}
else if (ans[i - x] == -1) {
ans[i - x] = 1;
}
}
else if (i + x <= n) {
if (ans[i + x] == 0) {
f = false;
break;
}
else if (ans[i + x] == -1) {
ans[i + x] = 1;
}
}
else {
f = false;
break;
}
}
}
if (f) {
for (int i = 1; i <= n; i++) {
if (ans[i] == -1) printf("1");
else printf("%d", ans[i]);
}
printf("\n");
}
else printf("-1\n");
}
return 0;
}
Zigzags (前后缀+枚举)
题解:
给定一数组a
, 设
1
<
=
i
<
j
<
k
<
l
<
=
n
1 <= i < j < k < l <= n
1<=i<j<k<l<=n , 求四元组
(
i
,
j
,
k
,
l
)
(i, j, k, l)
(i,j,k,l) 个数,
四元组 ( i , j , k , l ) : a i = a k 且 a j = a l (i,j,k,l) : a_i = a_k \text{且} a_j = a_l (i,j,k,l):ai=ak且aj=al
思路:
预处理前缀pre
,后缀 suf
枚举
j
,
k
j, k
j,k , 每次的贡献是j
前面的 a[k]
的个数 * k
后面的a[j]
的个数
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define eps 1e-9
#define INF 0x3f3f3f3f
#define pb push_back
#define mk make_pair
#define fi first
#define se second
using namespace std;
typedef unsigned int UI;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> P;
const int N = 3e3 + 10;
int pre[N][N], suf[N][N]; //pre[i][j]表示在i之前有多少个j(i不算) ,suf同理,不过是后缀
int n;
vector<int> a(N);
int main () {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i <= n; i++) { //初始化
pre[1][i] = 0;
suf[n][i] = 0;
}
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
//预处理前缀数组
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= n; j++) pre[i][j] = pre[i - 1][j];
pre[i][a[i - 1]] = pre[i - 1][a[i - 1]] + 1;
}
//处理后缀数组
for (int i = n - 1; i >= 1; i--) {
for (int j = 1; j <= n; j++) suf[i][j] = suf[i + 1][j];
suf[i][a[i + 1]] = suf[i + 1][a[i + 1]] + 1;
}
// printf("pre:\n");
// for (int i = 1; i <= n; i++) {
// printf("第i个前: ");
// for (int j = 1; j <= n; jt++) {
// printf("%d有 : %d ", j, pre[i][j]);
// }
// printf("\n");
// }
// printf("suf:\n");
// for (int i = 1; i <= n; i++) {
// printf("第i个后: ");
// for (int j = 1; j <= n; j++) {
// printf("%d有 : %d ", j, suf[i][j]);
// }
// printf("\n");
// }
ll ans = 0;
for (int j = 1; j <= n; j++) {
for (int k = j + 1; k <= n; k++) {
ans += 1LL * pre[j][a[k]] * suf[k][a[j]];
}
}
printf("%lld\n", ans);
}
return 0;
}