A题:
签到题,可以优化成sum为0,输入一个数后减去这个数进行输出。
inline void solve() {
int n; cin >> n;
int sum = 0;
for (int i = 1; i <= n - 1; i ++ ) {
int x; cin >> x;
sum += x;
}
cout << -sum << endl;
return;
}
B题:
按题意模拟即可,用了cnt存次数,如果相同次数的不是两个(因为0个的没有存)那么就输出错误,否则Yes
inline void solve() {
string s; cin >> s;
map<char, int> p;
for (auto c : s) {
p[c] ++;
}
bool ok = true;
map<int, int> cnt;
for (auto t : p) {
cnt[t.second] ++;
}
for (auto t : cnt) {
if (t.second != 2) ok = false;
}
if (ok) cout << "Yes\n";
else cout << "No\n";
return;
}
C题:
还是模拟,重要的是子序列,用到了双指针的思想,如果相同则cnt进行移位。
inline void solve() {
string s, t;
cin >> s >> t;
int cnt = 0;
if (t[2] == 'X') {
for (int i = 0; i < s.size(); i ++ ) {
if (toupper(s[i]) == t[cnt]) {
cnt ++;
}
if (cnt == 2) break;
}
if (cnt == 2) cout << "Yes\n";
else cout << "No\n";
}else {
for (int i = 0; i < s.size(); i ++ ) {
if (toupper(s[i]) == t[cnt]) {
cnt ++;
}
if (cnt == 3) break;
}
if (cnt == 3) cout << "Yes\n";
else cout << "No\n";
}
return;
}
D题:
模拟线段数的查询过程,
线段树最下面对应题目中的j == 0,然后逐级往上看,如果当前节点能够直接返回那么一定是最赚的,否则再进行查询。
vector<PLL> ans;
void query(ll l, ll r, ll L, ll R) {
if (l >= L && r <= R) {
ans.push_back({l, r + 1});
return;
}
ll mid = l + r >> 1;
if (L <= mid) query(l, mid, L, R);
if (R > mid) query(mid + 1, r, L, R);
}
inline void solve() {
ll l, r; cin >> l >> r;
query(0, qmi(2, 60) - 1, l , r - 1);
sort(ans.begin(), ans.end());
cout << ans.size() << endl;
for (auto &[x, y] : ans) {
cout << x << ' ' << y << endl;
}
return;
}
E题: Weighted Tic-Tac-Toe
两者都已最优方式放置,经典博弈论。
失败的条件是连成一条线或者总分比另外一个人低,这对应了f中的上面两个return情况(0代表先手获胜,1代表后手获胜)。
接着要枚举状态,如果当前位置没人放置,如果当前的人放了这个位置,之后获胜的还是这个人,那么就是必胜态,即f(now ^ 1, nxt) == now
否则则在dp中记录now ^ 1,并且返回now ^ 1
(期间用到记忆化搜索优化)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int dp[1 << 18];
bool vis[1 << 18];
int A[9];
int line[8] = {0b111, 0b111000, 0b111000000,
0b1001001, 0b10010010, 0b100100100,
0b100010001, 0b1010100};
bool get_bit(int x, int v) {
return (x >> v) & 1;
}
int f(int now, array<int, 2> state) {
for (int x : line) {
if (x == (state[0] & x)) return 0;
if (x == (state[1] & x)) return 1;
}
if ((state[0] | state[1]) == 511) {
ll v = 0;
for (int i = 0; i < 9; i ++ ) {
if (get_bit(state[0], i)) {
v += A[i];
}else {
v -= A[i];
}
}
return v < 0;
}
if (vis[state[0] | (state[1] << 9)]) return dp[state[0] | (state[1] << 9)];
vis[state[0] | (state[1] << 9)] = 1;
dp[state[0] | state[1] << 9] = now;
for (int i = 0; i < 9; i ++ ) {
if (get_bit(state[0], i) || get_bit(state[1], i)) continue;
array<int, 2> nxt = state;
nxt[now] |= 1 << i;
if (f(now ^ 1, nxt) == now) return now;
}
dp[state[0] | (state[1] << 9)] = now ^ 1;
return now ^ 1;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
for (int i = 0; i < 9; i ++ ) cin >> A[i];
if (!f(0, {0, 0})) {
cout << "Takahashi\n";
}else {
cout << "Aoki\n";
}
return 0;
}