Atcoder Beginner Contest 425
A
按照题意计算即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
int n, ans = 0;
scanf ("%lld", &n);
for (int i = 1; i <= n; i++)
ans += ((i & 1) ? -1 : 1) * i * i * i;
printf ("%lld\n", ans);
return 0;
}
B
开桶计出现次数看有没有出现多次的即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int N, idx;
int a[15], ton[15], num[15];
signed main() {
scanf ("%lld", &N);
for (int i = 1; i <= N; i++) {
scanf ("%lld", &a[i]);
if (~a[i]) ton[a[i]]++;
}
for (int i = 1; i <= N; i++) {
if (ton[i] > 1) {
printf ("No\n");
return 0;
}
}
for (int i = 1; i <= N; i++) {
if (!ton[i]) num[++idx] = i;
}
printf ("Yes\n");
for (int i = 1, j = 1; i <= N; i++) {
if (~a[i])
printf ("%lld ", a[i]);
else
printf ("%lld ", num[j++]);
}
return 0;
}
C
既然是头移到尾,考虑直接复制一份 \(a\) 数组,同时计前缀和。那么只需要维护序列开头的位置即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 2e5 + 10;
int N, Q;
int a[maxn << 1], sum[maxn << 1], head;
signed main() {
scanf ("%lld", &N);
scanf ("%lld", &Q);
for (int i = 1; i <= N; i++)
scanf ("%lld", &a[i]), a[i + N] = a[i];
for (int i = 1; i <= N * 2; i++)
sum[i] = sum[i - 1] + a[i];
head = 0;
for (int _ = 1; _ <= Q; _++) {
int opt;
scanf ("%lld", &opt);
if (opt == 1) {
int c;
scanf ("%lld", &c);
head = (head + c) % N;
}
if (opt == 2) {
int l, r;
scanf ("%lld %lld", &l, &r);
printf ("%lld\n", sum[head + r] - sum[head + l - 1]);
}
}
return 0;
}
D
感觉遇到过。很经典的扩散问题啊。
直接考虑从黑点 bfs,但是要注意每次更新不能直接更新遍历到的新点,而是一轮过后统一更新,不然会影响到其他点的判断。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 3e5 + 10;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int H, W;
char str[maxn];
queue<pair<int,int>> q, upd;
signed main() {
scanf ("%lld", &H);
scanf ("%lld", &W);
int mat[H + 5][W + 5] = {};
bool vis[H + 5][W + 5] = {};
memset (vis, false, sizeof(vis));
for (int i = 1; i <= H; i++) {
scanf ("%s", str + 1);
for (int j = 1; j <= W; j++) {
if (str[j] == '#') mat[i][j] = 1;
else mat[i][j] = 0;
}
}
for (int i = 1; i <= H; i++) {
for (int j = 1; j <= W; j++) {
if (mat[i][j])
q.push(make_pair(i, j));
}
}
for (int _ = 1; ; _++) {
while (!q.empty()) {
auto t = q.front();
q.pop();
int x = t.first, y = t.second;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 || nx > H || ny < 1 || ny > W) continue;
if (mat[nx + 1][ny] + mat[nx][ny + 1] + mat[nx - 1][ny] + mat[nx][ny - 1] == 1 && !mat[nx][ny]) upd.push(make_pair(nx, ny));
// vis[nx][ny] = true;
}
}
if (upd.empty()) break;
while (!upd.empty()) {
auto t = upd.front();
upd.pop();
mat[t.first][t.second] = 1;
q.push(make_pair(t.first, t.second));
}
}
int sum = 0;
for (int i = 1; i <= H; i++) {
for (int j = 1; j <= W; j++)
sum += mat[i][j];
}
printf ("%lld\n", sum);
return 0;
}
E
第一反应是组合数学,因为 \(C_i\) 个对应的同一个数比较明显的。每次从剩余空位中选即可。记 \(sum = \sum\limits_{i=1}^{n}{C_i}\),答案 \(\prod\limits_{i=1}^{n}{\binom{sum - \sum\limits_{j=1}^{i-1}{C_i}}{C_i}}\)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 3e5 + 10;
int Test, mod;
int N, c[maxn], sum[maxn];
int combine[5005][5005];
void init() {
combine[0][0] = 1;
for (int i = 1; i <= 5000; i++) {
combine[i][0] = 1;
for (int j = 1; j <= 5000; j++)
combine[i][j] = (combine[i - 1][j - 1] + combine[i - 1][j]) % mod;
}
}
void sol() {
cin >> N;
for (int i = 1; i <= N; i++)
cin >> c[i], sum[i] = sum[i - 1] + c[i];
int ans = 1;
for (int i = 1; i <= N; i++)
ans = (ans * combine[sum[N] - sum[i - 1]][c[i]]) % mod;
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> Test >> mod;
init();
while (Test--) sol();
return 0;
}
F
\(N \leq 22\),考虑状压。添加不好做,正难则反看做删除的方案数。
记 \(f_S\) 表示已经删除的集合,则有转移:\(f_{S \mid 2^i} \leftarrow f_{S \mid 2 ^i} + f_{S}\)。但是值得注意的,对于相邻的相同字符 \(s_i,s_j\),删除了 \(s_i\) 或 \(s_j\) 的结果一样,直接算会算重贡献。每次删除的相邻两个不同时才可转移。
答案即为 \(f_{2^N - 1}\)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 998244353;
int N;
char s[25];
int f[1 << 25];
signed main() {
scanf ("%lld %s", &N, s);
f[0] = 1;
for (int st = 0; st < (1 << N); st++) {
char ch = '#';
for (int i = 0; i < N; i++) {
if (!((st >> i) & 1)) {
if (ch != s[i])
f[st | (1 << i)] = (f[st | (1 << i)] + f[st]) % mod;
ch = s[i];
}
}
}
printf ("%lld\n", f[(1 << N) - 1]);
return 0;
}

浙公网安备 33010602011771号