QOJ
题解
]
ARC194D Reverse Brackets
一次选中的区间一定是合法括号串,合法括号串翻转后仍然是一个合法括号串。
如果我们把整个序列拆成一个极长合法括号串序列,翻转就相当于序列的一个子串的 reverse。
每次选一个子串的 reverse 其实相当于可以任意排列,因为可以每次选取子串长度为 $2$,那么就类似于冒泡排序,可以任意换位。
那么对答案的贡献就是多重集的排列,即序列长度阶乘除以每个的出现次数的阶乘,然后对拆成后的合法括号串递归下去即可。
更好的办法是把括号序列转成树结构,然后用树哈希来判重,代码更好写。
#include<bits/stdc++.h>
#define siz(x) int((x).size())
#define all(x) std::begin(x),std::end(x)
#define fi first
#define se second
using namespace std;
using unt=unsigned;
using loli=long long;
using lolu=unsigned long long;
using pii=pair<int,int>;
mt19937_64 rng(random_device{}());
lolu shift(lolu x){
static lolu mask=rng();
x^=x<<14;
x^=x>>3;
x^=x<<7;
return x^mask;
}
constexpr int N=5007,P=998244353;
struct mint{
int d;
mint()=default;
mint(int x):d(x){}
friend std::istream&operator>>(std::istream&x,mint&y){return x>>y.d;}
friend std::ostream&operator<<(std::ostream&x,mint y){return x<<y.d;}
friend mint operator+(mint x,mint y){return (x.d+=y.d)<P?x.d:x.d-P;}
mint&operator+=(mint z){return (d+=z.d)<P?d:d-=P,*this;}
friend mint operator-(mint x,mint y){return (x.d-=y.d)<0?x.d+P:x.d;}
mint&operator-=(mint z){return (d-=z.d)<0?d+=P:d,*this;}
friend mint operator*(mint x,mint y){return int(1ll*x.d*y.d%P);}
mint&operator*=(mint z){return d=int(1ll*d*z.d%P),*this;}
static mint qpow(int x,int y=P-2){int z=1;for(;y;y>>=1,x=int(1ll*x*x%P))if(y&1)z=int(1ll*x*z%P);return z;}
friend mint operator/(mint x,mint y){return x*=qpow(y.d);}
mint&operator/=(mint z){return (*this)*=qpow(z.d);}
friend mint operator^(mint x,mint y){return qpow(x.d,y.d);}
mint&operator^=(mint z){return *this=qpow(d,z.d);}
mint operator()(mint z)const{return qpow(d,z.d);}
mint&operator[](mint z){return *this=qpow(d,z.d);}
mint inv()const{return qpow(d);}
mint pow(mint z)const{return qpow(d,z.d);}
int operator+()const{return d;}
mint operator-()const{return d?P-d:0;}
int operator~()const{return ~d;}
};
mint operator""_m(lolu x){return mint(int(x%P));}
int n;
string a;
lolu h[N];
basic_string<int>g[N];
stack<int>s;
unordered_map<lolu,int>mp;
mint ans=1,fac[N],inv[N];
void dfs(int u){
h[u]=1;
for(int v:g[u]){
dfs(v);
h[u]+=shift(h[v]);
}
mp.clear();
for(int v:g[u])
mp[h[v]]++;
ans*=fac[siz(g[u])];
for(auto[x,y]:mp)
ans*=inv[y];
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);cin.tie(nullptr);
fac[0]=inv[0]=1;
for(int i=1;i<N;i++)fac[i]=fac[i-1]*i;
inv[N-1]=fac[N-1].inv();
for(int i=N-2;i;i--)inv[i]=inv[i+1]*(i+1);
cin>>n;
s.push(0);
for(int i=1;i<=n;i++){
char c;cin>>c;
if(c=='(')g[s.top()]+=i,s.push(i);
else s.pop();
}
dfs(0);
cout<<ans;
return 0;
}