T1:Order Something Else

模拟

代码实现
n, p, q = map(int, input().split())
d = list(map(int, input().split()))
print(min(p, q+min(d)))

T2:Strictly Superior

模拟

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> p(n);
vector<vector<int>> f(n);
rep(i, n) {
int c;
cin >> p[i] >> c;
f[i] = vector<int>(c);
rep(j, c) cin >> f[i][j];
}
rep(i, n)rep(j, n) if (i != j) {
if (p[i] < p[j]) continue;
bool ok = true;
for (int e : f[i]) {
if (find(f[j].begin(), f[j].end(), e) == f[j].end()) ok = false;
}
if (!ok) continue;
if (p[i] == p[j] and f[i] == f[j]) continue;
puts("Yes");
return 0;
}
puts("No");
return 0;
}
// 用 bitset 实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> p(n);
vector<bitset<101>> f(n);
rep(i, n) {
int c;
cin >> p[i] >> c;
rep(j, c) {
int e;
cin >> e;
f[i][e] = 1;
}
}
rep(i, n)rep(j, n) if (i != j) {
if (p[i] < p[j]) continue;
if ((f[i]&f[j]) != f[i]) continue;
if (p[i] == p[j] and f[i] == f[j]) continue;
puts("Yes");
return 0;
}
puts("No");
return 0;
}

T3:Reversible

可以先给木棍确定一个方向,只考虑以某个端点开始的字典序更小的字符串
然后用 set 来维护即可

代码实现
n = int(input())
st = set()
for _ in range(n):
s = input()
st.add(min(s, s[::-1]))
print(len(st))

T4:Peaceful Teams

暴力 dfs 即可

从第一个选手开始,由 dfs 决定进入第几个队伍,最后检查队伍数量即可

image

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, t, m;
cin >> n >> t >> m;
vector bad(n, vector<bool>(n));
rep(i, m) {
int a, b;
cin >> a >> b;
--a; --b;
bad[a][b] = true;
bad[b][a] = true;
}
int ans = 0;
vector<vector<int>> team;
auto f = [&](auto f, int i) -> void {
if (i == n) {
if (team.size() == t) ans++;
return;
}
rep(j, team.size()) {
bool ok = true;
for (int p : team[j]) if (bad[i][p]) ok = false;
if (!ok) continue;
team[j].push_back(i);
f(f, i+1);
team[j].pop_back();
}
team.push_back(vector<int>(1, i));
f(f, i+1);
team.pop_back();
};
f(f, 0);
cout << ans << '\n';
return 0;
}

也可以用状压dp解决

dp[S][i] 表示将 S 中的所有选手分成 i 个队伍且不把性格不和的选手分到同一组的方案数

时间复杂度为 O(3NT)

T5:NAND repeatedly

dp[n][k] 表示在 1in 中满足 f(i,n)=ki 的个数

代码实现
#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;
string s;
cin >> n >> s;
ll ans = 0;
vector<int> d(2);
rep(i, n) {
int x = s[i]-'0';
if (x == 0) {
d[1] += d[0]; d[0] = 0;
}
else {
swap(d[0], d[1]);
}
d[x]++;
ans += d[1];
}
cout << ans << '\n';
return 0;
}

T6:Make 10 Again

容易发现,如果投掷出的点数大于 10 则对答案没有贡献

dp[i][S] 表示用投掷的前 i 个筛子所能生成的值域在 010 中的集合为 S 的概率

代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using mint = modint998244353;
int main() {
int n;
cin >> n;
const int m = 10;
const int m2 = 1<<(m+1);
vector<mint> dp(m2);
dp[1] = 1;
rep(i, n) {
int a;
cin >> a;
vector<mint> p(m2);
swap(dp, p);
rep(s, m2) {
p[s] /= a;
for (int x = 1; x <= min(m, a); ++x) {
dp[(s|s<<x)&(m2-1)] += p[s];
}
dp[s] += p[s]*max(0, a-m); // 对于 a >= 10 的部分不产生贡献,只有前面的 i-1 个骰子有贡献
}
}
mint ans;
rep(s, m2) if (s>>m&1) ans += dp[s];
cout << ans.val() << '\n';
return 0;
}