"蔚来杯"2022牛客暑期多校训练营8 题解
D. Poker Game: Decision
对抗搜索+模拟比较两副牌的大小,具体看代码。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int INF = 10;
const int MAXN = 1e6 + 5;
struct Node {
pii p[10]; int num = 0;
pii init(string s) {
pii cur;
if(s[0] == 'T') s[0] = '0' + 10;
else if(s[0] == 'J') s[0] = '0' + 11;
else if(s[0] == 'Q') s[0] = '0' + 12;
else if(s[0] == 'K') s[0] = '0' + 13;
else if(s[0] == 'A') s[0] = '0' + 14;
cur = {s[0] - '0', s[1]};
return cur;
}
void push_back(string s) { p[++num] = init(s); }
void pop_back() { --num; }
}A, B, AA, BB, NUL;
string ss[10];
int st[10], Anum[20], Bnum[20];
pii q[20], num[20];
int Level(Node x) {
int lvl = 1; x.num = 5;
sort(x.p + 1, x.p + x.num + 1);
bool flag, flag1, flag2;
flag1 = 0, flag2 = 1;
if(x.p[1].fi + 1 == x.p[2].fi && x.p[2].fi + 1 == x.p[3].fi && x.p[3].fi + 1 == x.p[4].fi && x.p[4].fi + 1 == x.p[5].fi ) flag1 = 1;
if(x.p[1].fi == 2 && x.p[2].fi == 3 && x.p[3].fi == 4 && x.p[4].fi == 5 && x.p[5].fi == 14 ) flag1 = 1;
for(int i = 2; i <= x.num; i++) if(x.p[i].se != x.p[i - 1].se) flag2 = 0;
if(flag1 && flag2) lvl = 9;
if(lvl == 9 && x.p[5].fi == 14 ) lvl = 10;
if(lvl >= 9) return lvl;
flag = 0;
if(x.p[1].fi == x.p[2].fi && x.p[2].fi == x.p[3].fi && x.p[3].fi == x.p[4].fi) flag = 1;
if(x.p[2].fi == x.p[3].fi && x.p[3].fi == x.p[4].fi && x.p[4].fi == x.p[5].fi) flag = 1;
if(flag) return 8;
flag = 0;
if(x.p[1].fi == x.p[2].fi && x.p[2].fi == x.p[3].fi && x.p[4].fi == x.p[5].fi) flag = 1;
if(x.p[1].fi == x.p[2].fi && x.p[3].fi == x.p[4].fi && x.p[4].fi == x.p[5].fi) flag = 1;
if(flag) return 7;
flag = 1;
for(int i = 2; i <= x.num; i++) if(x.p[i].se != x.p[i - 1].se) flag = 0;
if(flag) return 6;
flag = 0;
if(x.p[1].fi + 1 == x.p[2].fi && x.p[2].fi + 1 == x.p[3].fi && x.p[3].fi + 1 == x.p[4].fi && x.p[4].fi + 1 == x.p[5].fi ) flag = 1;
if(x.p[1].fi == 2 && x.p[2].fi == 3 && x.p[3].fi == 4 && x.p[4].fi == 5 && x.p[5].fi == 14 ) flag = 1;
if(flag) return 5;
flag = 0;
for(int i = 3; i <= x.num; i++) if(x.p[i].fi == x.p[i - 1].fi && x.p[i].fi == x.p[i - 2].fi) flag = 1;
if(flag) return 4;
flag = 0;
for(int i = 2; i <= x.num; i++) for(int j = i + 2; j <= x.num; j++) if(x.p[i].fi == x.p[i - 1].fi && x.p[j].fi == x.p[j - 1].fi) flag = 1;
if(flag) return 3;
flag = 0;
for(int i = 2; i <= x.num; i++) if(x.p[i].fi == x.p[i - 1].fi) flag = 1;
if(flag) return 2;
return 1;
}
void Print(Node x) {
for(int i = 1; i <= 5; i++) cout << x.p[i].fi << "," << x.p[i].se << " "; cout << " poker\n";
sort(x.p + 1, x.p + 5 + 1);
for(int i = 1; i <= 5; i++) cout << x.p[i].fi << "," << x.p[i].se << " "; cout << " sort poker\n";
cout << Level(x) << " level\n\n";
}
void Sort(int* cnum, Node x, int cnt = 0) {
for(int i = 1; i <= 14; i++) num[i] = {0, i};
for(int i = 1; i <= 5; i++) num[ x.p[i].fi ].fi++;
sort(num + 1, num + 1 + 14, [&](const pii& a, const pii& b) {
if(a.fi == b.fi) return a.se > b.se;
return a.fi > b.fi;
});
for(int i = 1; i <= 14; i++) {
if(num[i].fi == 0) break;
for(int j = 1; j <= 5; j++) if(x.p[j].fi == num[i].se) q[++cnt] = x.p[j];
}
for(int i = 1; i <= 5; i++) cnum[i] = q[i].fi;
if(cnum[1] == 14 && cnum[2] == 5 && cnum[3] == 4 && cnum[4] == 3 && cnum[5] == 2 ) cnum[1] = 5, cnum[2] = 4, cnum[3] = 3, cnum[4] = 2, cnum[5] = 1;
}
int cal() {
int lvlA = Level(A), lvlB = Level(B);
if(lvlA > lvlB) return 1;
else if(lvlA < lvlB) return -1;
else {
Sort(Anum, A); Sort(Bnum, B);
for(int i = 1; i <= 5; i++) {
if(Anum[i] < Bnum[i]) return -1;
if(Anum[i] > Bnum[i]) return 1;
}
return 0;
}
}
int dfs(int pos,int type,int Alpha,int Beta) {
if(pos == 7) return cal();
int ans = type?INF:-INF;
for(int i=1;i<=6;++i){
if(st[i] == 1) continue;
st[i] = 1;
if(pos % 2) A.push_back(ss[i]);
else B.push_back(ss[i]);
int tmp = dfs(pos+1,type ^ 1,Alpha,Beta);
type ? Beta = min(Beta,tmp) : Alpha = max(Alpha,tmp);
st[i] = 0;
if(pos % 2) A.pop_back();
else B.pop_back();
if(Alpha >= Beta) break;
}
return type ? Beta : Alpha;
}
void Solve() {
string s1, s2; A.num = 0, B.num = 0;
cin >> s1 >> s2; A.push_back(s1), A.push_back(s2);
cin >> s1 >> s2; B.push_back(s1), B.push_back(s2);
for(int i = 1; i <= 6; i++) cin >> ss[i];
int cur = dfs(1, 0, -INF, INF);
if(cur == 1) cout << "Alice";
else if(cur == 0) cout << "Draw";
else cout << "Bob";
cout << "\n";
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T; cin >> T;
while(T--) Solve();
return 0;
}
F. Longest Common Subsequence
对于序列 \(t\),发现如果有一个数和 \(s\) 中的某一个数相等,那么根据构造方式,可知接在其后面的所有数都相等,其 lcs 一定是连续的。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 5;
int n, m, p, x, a, b, c, len, vals[MAXN], minn[MAXN], A[MAXN];
int Map(int x) {
int pos = lower_bound(vals + 1, vals + 1 + len, x) - vals;
if(pos <= 0 || pos > len || vals[pos] != x) return 0;
return pos;
}
void Solve() {
cin >> n >> m >> p >> x >> a >> b >> c;
for(int i = 1; i <= n; i++) {
x = (a * x % p * x % p + b * x % p + c % p) % p;
vals[i] = A[i] = x;
minn[i] = INF;
}
sort(vals + 1, vals + 1 + n);
len = unique(vals + 1, vals + 1 + n) - vals - 1;
for(int i = n; i >= 1; i--) {
A[i] = Map(A[i]);
minn[ A[i] ] = i;
}
int ans = 0;
for(int i = 1; i <= m; i++) {
x = (a * x % p * x % p + b * x % p + c) % p;
int cur = Map(x);
if(cur) ans = max(ans, (int)min(m - i + 1, n - minn[cur] + 1) );
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T; cin >> T;
while(T--) Solve();
return 0;
}