Mobile wallpaper 1Mobile wallpaper 2Mobile wallpaper 3Mobile wallpaper 4Mobile wallpaper 5
1985 字
10 分钟
2026寒假集训个人训练赛第十八场
2026-02-13
统计加载中...

A. 间隔#

不可能当且仅当有相邻相等的且不是全部相等,否则最小间隔就是所有间隔的 gcd。

#include <iostream>
#include <vector>
using namespace std;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
bool f = true;
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
int g = 0;
for (int i = 2; i <= n; ++i) {
if (a[i] - a[i - 1] == 0 && a[i] != a[1]) {
cout << -1 << endl;
f = false;
break;
}
g = gcd(g, a[i] - a[i - 1]);
}
if (!f) continue;
if (g == 0) {
cout << 0 << endl;
continue;
}
long long cnt = 0;
for (int i = 2; i <= n; ++i) {
cnt += (a[i] - a[i - 1]) / g - 1;
}
cout << cnt << endl;
}
return 0;
}

B. 密码锁#

直接暴力枚举 DP 即可。

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 30, M = 1010, MOD = 1000000007;
LL f[M][N][N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m, t;
cin >> n >> m >> t;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
f[1][i][j] = 1;
}
}
for (int i = 2; i <= t; ++i) {
int dis;
cin >> dis;
for (int j = 1; j <= n; ++j) {
for (int k = 1; k <= m; ++k) {
for (int x = 1; x <= n; ++x) {
for (int y = 1; y <= m; ++y) {
if (abs(x - j) + abs(y - k) <= dis) f[i][j][k] = (f[i][j][k] + f[i - 1][x][y]) % MOD;
}
}
}
}
}
LL res = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
res = (res + f[t][i][j]) % MOD;
}
}
cout << res << endl;
return 0;
}

C. 上街#

这是一个非常非常恶心的大模拟 + Dijkstra,题目基本上是纯板子,但是写着真恶心。

#include <iostream>
#include <queue>
#include <cstring>
#include <tuple>
using namespace std;
typedef long long LL;
const int N = 210, M = 60;
const int deltx[] = {1, 0, -1, 0}, delty[] = {0, -1, 0, 1};
int a[N][N], b[N][N], d[N][N], e[N][N];
int dis[N][N][4][M];
bool vis[N][N][4][M];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m, t, xe, ye;
cin >> n >> m >> t >> xe >> ye;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
cin >> a[i][j] >> b[i][j] >> d[i][j] >> e[i][j];
}
}
memset(dis, 0x3f, sizeof(dis));
priority_queue<tuple<int, int, int, int, int>, vector<tuple<int, int, int, int, int>>, greater<tuple<int, int, int, int, int>>> q;
dis[1][1][0][0] = 0;
q.emplace(dis[1][1][0][0], 0, 0, 1, 1);
while (!q.empty()) {
auto [_, ct, dir, x, y] = q.top();
q.pop();
if (vis[x][y][dir][ct]) continue;
vis[x][y][dir][ct] = true;
int &dx = dis[x][y][dir][ct];
if (x == xe && y == ye) {
cout << dx << endl;
return 0;
}
int tx, ty, ndir, nt, w;
if (a[x][y] == 0 && b[x][y] == 0) {
for (int tt = dir - 1; tt <= dir + 1; ++tt) {
ndir = (tt + 4) % 4, tx = x + deltx[ndir], ty = y + delty[ndir];
if (tx <= 0 || tx > n || ty <= 0 || ty > m) continue;
if (ndir == 0) w = d[x][y];
else if (ndir == 1) w = e[tx][ty];
else if (ndir == 2) w = d[tx][ty];
else w = e[x][y];
if (t == 0) nt = 0;
else nt = (ct + w) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
}
else if (dir == 0) {
if (y > 1) { // you
ndir = 1, tx = x, ty = y - 1, w = e[tx][ty], nt = (ct + e[tx][ty]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (x < n) { // qian
ndir = 0, tx = x + 1, ty = y, w = (ct < a[x][y] ? a[x][y] - ct : 0) * 10 + d[x][y], nt = (max(ct, a[x][y]) + d[x][y]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (y < m) { // zuo
ndir = 3, tx = x, ty = y + 1, w = (ct < a[x][y] ? a[x][y] - ct : 0) * 10 + e[x][y], nt = (max(ct, a[x][y]) + e[x][y]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
}
else if (dir == 1) {
if (x > 1) { // you
ndir = 2, tx = x - 1, ty = y, w = d[tx][ty], nt = (ct + d[tx][ty]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (y > 1) { // qian
ndir = 1, tx = x, ty = y - 1, w = ct < a[x][y] ? e[tx][ty] : (t - ct) * 10 + e[tx][ty], nt = ((ct < a[x][y] ? ct : 0) + e[tx][ty]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (x < n) { // zuo
ndir = 0, tx = x + 1, ty = y, w = ct < a[x][y] ? d[x][y] : (t - ct) * 10 + d[x][y], nt = ((ct < a[x][y] ? ct : 0) + d[x][y]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
}
else if (dir == 2) {
if (y < m) { // zuo
ndir = 3, tx = x, ty = y + 1, w = e[x][y], nt = (ct + e[x][y]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (x > 1) { // qian
ndir = 2, tx = x - 1, ty = y, w = (ct < a[x][y] ? a[x][y] - ct : 0) * 10 + d[tx][ty], nt = (max(ct, a[x][y]) + d[tx][ty]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (y > 1) { // zuo
ndir = 1, tx = x, ty = y - 1, w = (ct < a[x][y] ? a[x][y] - ct : 0) * 10 + e[tx][ty], nt = (max(ct, a[x][y]) + e[tx][ty]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
}
else { // dir == 3
if (x < n) { // you
ndir = 0, tx = x + 1, ty = y, w = d[x][y], nt = (ct + d[x][y]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (y < m) { // qian
ndir = 3, tx = x, ty = y + 1, w = ct < a[x][y] ? e[x][y] : (t - ct) * 10 + e[x][y], nt = ((ct < a[x][y] ? ct : 0) + e[x][y]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
if (x > 1) { // zuo
ndir = 2, tx = x - 1, ty = y, w = ct < a[x][y] ? d[tx][ty] : (t - ct) * 10 + d[tx][ty], nt = ((ct < a[x][y] ? ct : 0) + d[tx][ty]) % t;
int &dy = dis[tx][ty][ndir][nt];
if (dy > dx + w) dy = dx + w, q.emplace(dy, nt, ndir, tx, ty);
}
}
}
return 0;
}

D. 联通数#

所有两位及以上的全是 1 的数都能用 111 和 11 表示出来,先全用 111,然后一个一个反悔。显然反悔的步数不会超过 110 就一定能找到答案 / 判定不合法。

#include <iostream>
using namespace std;
typedef long long LL;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
LL n, k;
cin >> n >> k;
if (n % k == 0) {
n /= k;
LL t = n / 111;
bool f = false;
for (int i = 1; i <= t; ++i) {
if ((n - (LL)i * 111) % 11 == 0) {
f = true;
break;
}
}
if (f) cout << "YES" << endl;
else cout << "NO" << endl;
}
else cout << "NO" << endl;
}
return 0;
}

E. 赛博朋克#

F. 凌云渡#

G. 圣迹再临#

H. Wooden Sticks#

导弹拦截问题 一样,把一个维度排序,然后另一个维度贪心取。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 5010;
pair<LL, LL> a[N];
vector<LL> b;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i].first >> a[i].second;
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++i) {
int p = -1;
for (int j = 0; j < b.size(); ++j) {
if (b[j] <= a[i].second) {
if (p == -1) p = j;
else if (b[j] > b[p]) p = j;
}
}
if (p == -1) b.emplace_back(a[i].second);
else b[p] = a[i].second;
}
cout << b.size() << endl;
b.clear();
}
return 0;
}

I. Shipping containers#

如果间隔大于 n\sqrt{n} 那么单次修改次数不会超过 n\lfloor\sqrt{n}\rfloor,暴力修改,反之维护前缀和只会占用 O(nn)O(n\sqrt{n}) 的空间。分开做即可。

#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 100010;
int s[N][320], a[N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, k, l;
cin >> n >> k;
l = sqrt(n);
for (int i = 1; i <= k; ++i) {
int p, cnt, d;
cin >> p >> cnt >> d;
if (d > l) for (int j = 0; j < cnt; ++j) a[p + j * d]++;
else s[p][d]++, s[min(n + 1, p + d * cnt)][d]--;
}
for (int i = 1; i <= n; ++i) {
int t = a[i];
for (int j = 1; j <= l; ++j) {
if (i - j >= 0) s[i][j] += s[i - j][j];
t += s[i][j];
}
cout << t << ' ';
}
cout << endl;
return 0;
}
2026寒假集训个人训练赛第十八场
https://starlab.top/posts/2026wp18/
作者
Star
发布于
2026-02-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时