A. Pairing

模拟

代码实现
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> a(4);
cin >> a[0] >> a[1] >> a[2] >> a[3];
ranges::sort(a);
if (a[0] == a[1] and a[2] == a[3]) {
puts("2");
}
else if (a[0] == a[1]) {
puts("1");
}
else if (a[1] == a[2]) {
puts("1");
}
else if (a[2] == a[3]) {
puts("1");
}
else puts("0");
return 0;
}

B. Garbage Collection

答案为 drtqtqt+rt

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<int> q(n), r(n);
rep(i, n) cin >> q[i] >> r[i];
int Q;
cin >> Q;
rep(Qi, Q) {
int t, d;
cin >> t >> d;
--t;
d -= r[t];
int ans = (d+q[t]-1)/q[t]*q[t] + r[t];
cout << ans << '\n';
}
return 0;
}

C. Repeating

map 来维护每种数上一次出现的位置

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
map<int, int> last;
vector<int> ans(n);
rep(i, n) {
if (last.contains(a[i])) ans[i] = last[a[i]];
else ans[i] = -1;
last[a[i]] = i+1;
}
rep(i, n) cout << ans[i] << ' ';
return 0;
}

D. Count Simple Paths

dfs

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
const int di[] = {-1, 0, 1, 0};
const int dj[] = {0, 1, 0, -1};
int main() {
int h, w, k;
cin >> h >> w >> k;
vector<string> s(h);
rep(i, h) cin >> s[i];
auto dfs = [&](auto& f, int i, int j, int k) -> int {
if (k == 0) return 1;
s[i][j] = '*';
int res = 0;
rep(v, 4) {
int ni = i+di[v], nj = j+dj[v];
if (ni < 0 or nj < 0 or ni >= h or nj >= w) continue;
if (s[ni][nj] != '.') continue;
res += f(f, ni, nj, k-1);
}
s[i][j] = '.';
return res;
};
int ans = 0;
rep(si, h)rep(sj, w) {
if (s[si][sj] == '#') continue;
ans += dfs(dfs, si, sj, k);
}
cout << ans << '\n';
return 0;
}

E. Mod Sigma Problem

Si=k=0i1Ak

li<rAi=SrSl

注意到 (SrSl)modM=(SrmodMSlmodM)modM
下面默认之后的 Si 都是对 M 取模后的
显然 Si 的取值范围为 [0,M1]
SrSl<0,则 (SrSl)modM=SrSl+M
SrSl0,则 (SrSl)modM=SrSl

于是,l<r(SlSr)modM=l<r(SrSl)+l<rSl>SrM
其中 l<r(SrSl)+l<rSl>SrM 等于满足 Sl>Sl 的二元组 (l,r) 的个数 ×M
l<r(SrSl)=(l<rSr)(l<rSl)=rSr×rlSl×(Nl)
上面提到的满足 Sl>Sr 的二元组 (l,r) 的个数其实就是逆序数

代码实现
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<ll> s(n+1);
rep(i, n) s[i+1] = s[i]+a[i];
n = s.size();
rep(i, n) s[i] %= m;
ll ans = 0;
rep(r, n) ans += s[r]*r;
rep(l, n) ans -= s[l]*(n-l-1);
ll cnt = 0;
fenwick_tree<int> t(m);
rep(i, n) {
cnt += t.sum(s[i]+1, m);
t.add(s[i], 1);
}
ans += cnt*m;
cout << ans << '\n';
return 0;
}

F. Add One Edge 2

本质上是统计有多少个点对满足除了这两个点的度数以外位于这两个点的路径上的其他点的度数都是 3

dp[v] 表示在点 v 为根的子树中从点 v 开始的类似 33...32 的路径数
答案有两种情况:
一种是当点 v 的度数是 2 时,对答案的贡献就是 dp[u],其中点 u 是点 v 的儿子节点
另一种是当点 v 的度数是 3 时,对答案的贡献就是以点 vlca 的两边都是 33...2 形式的路径数
注意第一种会将 22 统计进去,所以最后要减去这一部分的贡献才是正确答案

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<vector<int>> to(n);
rep(i, n-1) {
int a, b;
cin >> a >> b;
--a; --b;
to[a].push_back(b);
to[b].push_back(a);
}
vector<int> deg(n);
rep(i, n) deg[i] = to[i].size();
ll ans = 0;
vector<ll> dp(n);
auto dfs = [&](auto& f, int v, int p=-1) -> void {
for (int u : to[v]) {
if (u == p) continue;
f(f, u, v);
if (deg[v] == 3) {
ans += dp[v]*dp[u];
}
if (deg[v] == 3) dp[v] += dp[u];
if (deg[v] == 2) {
ans += dp[u];
if (deg[u] == 2) ans--;
}
}
if (deg[v] == 2) dp[v]++;
};
dfs(dfs, 0);
cout << ans << '\n';
return 0;
}

G. Everlasting LIDS

性质1:

一个 (1,2,,n) 的排列 X 和一对相同形状的标准杨表是一一对应的

定义 PX 为杨表 ((x1x2)x3)x1

性质2:

PX 中第一行长度即为排列 XLIS 长度

性质3:

PX 中第一列长度即为排列 XLDS 长度

定义 QX 为记录表,即在对 PX 插入 xi 时将下标的 i 插入相应位置并维持 QXPX 的形状完全相同。显然,QX 也是一个杨表

回到原题,只需暴力dp求 PX 的方案数,而 QX 只需套钩长公式即可