A
暴力计算
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
int main()
{
int t; cin >> t;
while (t--) {
int a, b, c; cin >> a >> b >> c;
int ans = 0;
ans += 3 * min(c / 2, b);
ans += 3 * min(a, (b - min(c / 2, b)) / 2);
cout << ans << endl;
}
}
B
把每个物品分到m个盒子的全部可能性 -空(2^m-1),n个盒子即^n
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int mod = 1e9 + 7;
typedef long long ll;
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
int main()
{
int n, m; cin >> n >> m;
cout << qpow((qpow(2, m) - 1 + mod) % mod, n) << endl;
}
C
分析样例
n组,每次按照奇数组id+1,偶数组id-1分配
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int maxn = 300 + 5;
int ans[maxn];
int main()
{
int n; cin >> n;
for (int i = 1; i <= n; ++i) {
if (i & 1) ans[i] = n * (i - 1) + 1;
else ans[i] = n * i;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (j > 1) putchar(' ');
printf("%d", ans[j]);
if (j & 1) ans[j]++;
else ans[j]--;
}
putchar('\n');
}
}
D
分析机器人运行,发现即是机器人朝一个方向走遇到障碍物即要转弯
模拟机器人运行即可,注意每一行每一列只会走一次,直接排序障碍物,找出路径上与出发点前进方向上最近的点
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
vector<int> line[maxn], col[maxn];
bool less_cmp(int a, int b) { return a > b; }
struct Tre {
int a[3][maxn << 2];
void build(int rt, int l, int r) {
if (l == r) {
a[0][rt] = inf; a[1][rt] = -1;
return;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
a[0][rt] = min(a[0][rt << 1], a[0][rt << 1 | 1]);
a[1][rt] = max(a[1][rt << 1], a[1][rt << 1 | 1]);
}
void update(int rt, int l, int r, int pos) {
if (l == r) {
a[0][rt] = a[1][rt] = pos;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) update(rt << 1, l, mid, pos);
else update(rt << 1 | 1, mid + 1, r, pos);
a[0][rt] = min(a[0][rt << 1], a[0][rt << 1 | 1]);
a[1][rt] = max(a[1][rt << 1], a[1][rt << 1 | 1]);
}
int queryMin(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) return a[0][rt];
int mid = (l + r) >> 1, res = inf;
if (L <= mid) res = min(res, queryMin(rt << 1, l, mid, L, R));
if (mid < R) res = min(res, queryMin(rt << 1 | 1, mid + 1, r, L, R));
return res;
}
int queryMax(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) return a[1][rt];
int mid = (l + r) >> 1, res = -1;
if (L <= mid) res = max(res, queryMax(rt << 1, l, mid, L, R));
if (mid < R) res = max(res, queryMax(rt << 1 | 1, mid + 1, r, L, R));
return res;
}
} usedline, usedcol;
map<pair<int, int>, bool> check;
int main()
{
int n, m, k; scanf("%d%d%d", &n, &m, &k);
ll realk = 0;
for (int i = 1; i <= k; ++i) {
int x, y; scanf("%d%d", &x, &y);
if (check.count(make_pair(x, y))) continue;
realk++;
line[x].push_back(y);
col[y].push_back(x);
}
for (int i = 1; i <= n; ++i) line[i].push_back(0), line[i].push_back(m + 1);
for (int i = 1; i <= m; ++i) col[i].push_back(0), col[i].push_back(n + 1);
usedline.build(1, 0, n + 1); usedcol.build(1, 0, m + 1);
usedline.update(1, 0, n + 1, 0), usedline.update(1, 0, n + 1, n + 1);
usedcol.update(1, 0, m + 1, 0), usedcol.update(1, 0, m + 1, m + 1);
ll ans = 1;
int x = 1, y = 1, p = 0, flg = 1;
while (true) {
//cout << x << ", " << y << " : " << p << endl;
if (p == 0) {
sort(line[x].begin(), line[x].end());
int ret = *lower_bound(line[x].begin(), line[x].end(), y);
ret = min(ret, usedcol.queryMin(1, 0, m + 1, y + 1, m + 1));
//cout << ret << endl;
if (ret == y) break;
if (ret == y + 1) {
if (flg) { flg = 0; p = (p + 1) % 4; continue; }
else break;
}
usedline.update(1, 0, n + 1, x);
ans += ret - y - 1;
y = ret - 1; p = (p + 1) % 4;
if (flg) flg = 0;
}
else if (p == 1) {
sort(col[y].begin(), col[y].end());
int ret = *lower_bound(col[y].begin(), col[y].end(), x);
ret = min(ret, usedline.queryMin(1, 0, n + 1, x + 1, n + 1));
//cout << ret << endl;
if (ret == x || ret == x + 1) break;
usedcol.update(1, 0, m + 1, y);
ans += ret - x - 1;
x = ret - 1; p = (p + 1) % 4;
}
else if (p == 2) {
sort(line[x].begin(), line[x].end(), less_cmp);
int ret = *lower_bound(line[x].begin(), line[x].end(), y, less_cmp);
ret = max(ret, usedcol.queryMax(1, 0, m + 1, 0, y - 1));
//cout << ret << endl;
if (ret == y || ret == y - 1) break;
usedline.update(1, 0, n + 1, x);
ans += y - ret - 1;
y = ret + 1; p = (p + 1) % 4;
}
else {
sort(col[y].begin(), col[y].end(), less_cmp);
int ret = *lower_bound(col[y].begin(), col[y].end(), x, less_cmp);
ret = max(ret, usedline.queryMax(1, 0, n + 1, 0, x - 1));
//cout << ret << endl;
if (ret == x || ret == x - 1) break;
usedcol.update(1, 0, m + 1, y);
ans += x - ret - 1;
x = ret + 1; p = (p + 1) % 4;
}
}
cout << ((ans == 1ll * n * m - realk) ? "Yes" : "No") << endl;
}
E
我们需要计算(i,j)对数,枚举i,我们发现能到的最大的j和最小的j之间都能到达。把问题抽象为二维平面不经过障碍点,每次能向上或向下或向右能到达的最高点和最低点。
没有障碍点时会一直走斜线,按斜线保存x坐标,每次二分大于等于改点的斜线上的点,走到它的下面。
https://www.cnblogs.com/heyuhhh/p/11698762.html