考挂了 中午和某位强者去吃饭他说他状态不好 可能会挂 结果又是快Ak 了 然后我挂了 这就是 强者定律吧说着我要挂了 然后别人挂了...
今天得分 64 分T1 52 分 T3 12 分。丢人 and 很难受 也让我看清了生活的真相。世界上只有一种英雄主义就是 认清生活的真相之后依然还热爱生活。
有m个括号坏掉了 考虑组合 16分 爆搜 32 分dp 如何dp?这个dp 和普通的 括号匹配方案数即卡特兰数n^2递推不一样因为不需要记录还有多少个右括号已经用过了。
但是m个括号坏掉了 所以右括号也要记录个数 怎样能把整个括号序列都表达出来呢? 很有趣的问题 可以设 f[i][j][k] 表示已经形成了j个匹配 有效左括号为j 还剩下k个右括号的方案数。

//#include#include #include #include #include #include #include #include #include #include #include #include<string> #include #include #include #include #include
100分的话考虑折线法。我理解不够深刻 这里不敢赘述,

#includeusing namespace std; typedef long long ll; template inline void read(T &x) { x=0;T f=1,ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x*=f; } const ll mod=998244353; ll fac[2002002],inv[2002002],n,m,ans; inline ll pow(ll a,ll b) { ll res=1; while(b) { if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; } return res; } inline ll C(ll n,ll m) { if(m>n) return 0; if(m<0) return 0; if(n<0) return 0; return fac[n]*inv[m]%mod*inv[n-m]%mod; } inline ll c(ll n) {return (C(2ll*n,n)-C(2ll*n,n+1)+mod)%mod;} ll exctl(int n,int m) {return (C(2ll*n,n)-C(2*n,n-m-1)+mod)%mod;} int main() { freopen("excatalan.in","r",stdin); freopen("excatalan.out","w",stdout); read(n); read(m); fac[0]=1; for(int i=1;i<=2*n;i++) { fac[i]=fac[i-1]*i; fac[i]%=mod; } inv[2*n]=pow(fac[2*n],mod-2); for(int i=2*n-1;i>=0;i--) { inv[i]=inv[i+1]*(i+1); inv[i]%=mod; } if(m==0) ans=c(n); else ans=(exctl(n,m)-exctl(n,m-1)+mod)%mod; printf("%lld\n",ans); return 0; }
样例有点毒瘤其实 但是影响不大 原地爆炸qwq.算了十几分钟 觉得很毒瘤。
但是还是可以写的 考虑dp f[i][j] 表示以i为根的子树种大小为j的联通块期望混乱度 。 转移有点繁琐 这里不再赘述 是n^3的。
然后不会了 咕掉 不太能理解这个东西的思想。
考虑8分爆搜 然后观察题目显然的是序列必然为 奇数 且 有一定的 性质例如一个数一定比上上一个数大或者小什么的。
f[i][j][k] 考虑到了 第i个数且上一个数字是j 上上数字是k 的方案数。转移n^3 显然可以滚动数组。
不懂 咕掉。