题解:P17528 [JAG 2026 Summer Camp #1] Neighbour or Opposite
菜就多练神秘题。
由于匹配方式为
这样分割后,仍然有两条边特殊:
对于每一列,我对这一列的匹配操作只关心它的两个点是否被占用。于是设计 dp 状态,用一个两位二进制数
需要特判
时间复杂度
::::success[参考实现]
#include<bits/stdc++.h>
using namespace std;
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define rep2(i,x,y) for (int i=(x);i<(y);i++)
#define rec(i,x,y) for(int i = (x);i;i = (y))
#define dow(i,x,y) for (int i=(x);i>=(y);i--)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define mt empty
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define fil(a,b) memset((a),(b),sizeof(a))
#define int long long
#define ull unsigned long long
#define N 1005
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 998244353
#define ciallo return 0;
int n, ans1, ans2;
string s;
pair<int, int> solve(int n, string s, int s1, int s2) {
if (s1 && (s[1] == 'x' || s[2 * n] == 'x')) return {-inf, 0};
if (s2 && (s[n] == 'x' || s[n + 1] == 'x')) return {-inf, 0};
vector<int> f(4, -inf), g(4, -inf), cnt(4, 0), cnt2(4, 0);
cnt[0] = 1,f[0] =0;
rep(i, 1, n) {
int A = (s[i] == 'o'), B = (s[n + i] == 'o');
if (i == 1) {if (s1)A = 0;if (s2)B = 0;}
if (i == n) {if (s1)B = 0;if (s2)A = 0;}
int nxtA = 0, nxtB = 0;
if (i < n) {
nxtA = (s[i + 1] == 'o'), nxtB=(s[n + i + 1] == 'o');
if (i + 1 == n) {if (s1)nxtB = 0;if (s2)nxtA = 0;}
}
rep(j, 0, 3) { g[j] = -inf; cnt2[j] = 0; }
rep(l, 0, 3) {
if ((l & 1) && !A) continue;
if ((l & 2) && !B) continue;
rep(t,0,1){
if (t && ((l & 1) || (l & 2) || !A || !B)) continue;
rep(rA,0,1) {
if (rA && (!A ||(l & 1) || t|| i == n || !nxtA)) continue;
for (int rB = 0; rB <= 1; rB++) {
if (rB && (!B || (l & 2) || t || i == n || !nxtB)) continue;
int add = t + rA + rB,nm = (rA ? 1 : 0) | (rB ? 2 : 0);
if (f[l] + add > g[nm]) {
g[nm] = (f[l] + add) %mod;
cnt2[nm] = cnt[l];
} else if (f[l] + add == g[nm])
cnt2[nm] = (cnt2[nm] + cnt[l]) %mod;
}
}
}
}
rep(j,0,3){f[j] = g[j];cnt[j] = cnt2[j];}
}
return {s1+s2+f[0],cnt[0]};
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> n;cin >> s;s = " " + s;
if(n==1) {
if (s[1] == 'o' && s[2] == 'o')cout << 1 << ' ' << 1 << endl;
else cout << 0 << ' ' << 1 << endl;
ciallo}
rep(s1, 0, 1) {
rep(s2, 0, 1) {
auto r = solve(n, s, s1, s2);
int a1=r.fi,a2=r.se;
if(ans1 < a1){ans1 = a1;ans2 = a2;}
else if (ans1 == a1) {ans2 = (ans2+a2)%mod;}
}
}
cout << ans1 <<" "<< ans2;
ciallo
}
::::