[题解]P1641 生成字符串

P1641 [SCOI2010] 生成字符串

由题意可设\(f[i][j]\)表示用了\(i\)\(0\)\(j\)\(1\)的答案,那么有转移:

\[f[i][j]=\begin{cases} 0&i>j\\ f[i][j-1]&i=j\\ f[i-1][j]+f[i][j-1]&i<j\\ \end{cases}\]

状态数是\(O(n^2)\),转移是\(O(1)\),总时间复杂度\(O(n^2)\),期望得分\(30\text{ pts}\)


我们用数形结合的方式思考:

如图,我们将填\(1\)视为向右走\(1\)个单位长度,填\(0\)视为向上走\(1\)个单位长度,最终到达\((n,m)\)视为完成,此时点的轨迹形成了一条折线。每条折线对应一种方案,总方案数是\(C_{n+m}^n\)

显然,当前方案是合法的\(\iff\)折线的每个顶点都不在直线\(y=x\)上方。

换句话说,当前方案不合法\(\iff\)折线与\(y=x+1\)有交点。

对于每个不合法的方案,我们选定其中一个交点,将它之前的折线沿着\(y=x+1\)翻折,得到图中橙色的虚线。我们将橙色折线与剩余的红色折线形成的部分记作折线\(b\)

可以发现,\(b\)可以取到的形态,与不合法的方案是一一对应的。

所以不合法的方案数就是从\((-1,-1)\)走到\((n,m)\)的方案数,即\(C_{n+m}^{n+1}\)

因此合法方案数就是\(C_{n+m}^n-C_{n+m}^{n+1}\),可以化简得到\(\frac{(n+m)!\times (n-m+1)}{(n+1)!\times m!}\)

Catalan数\(H_n=C_{2n}^n-C_{2n}^{n-1}\)可以由此题的结论推得,相当于此题\(n=m\)的情况。

计算它需要使用逆元,此处使用费马小定理。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 1000010
#define mod 20100403
using namespace std;
int n,m,inv[N],inv_fact[N];
int fac(int r){
int ans=1;
for(int i=1;i<=r;i++) ans=ans*i%mod;
return ans;
}
signed main(){
cin>>n>>m;
inv_fact[1]=inv[1]=1;
for(int i=2;i<=n+1;i++) inv[i]=(-mod/i*inv[mod%i]%mod+mod)%mod;
for(int i=2;i<=n+1;i++) inv_fact[i]=inv_fact[i-1]*inv[i]%mod;
cout<<fac(n+m)*(n-m+1)%mod*inv_fact[n+1]%mod*inv_fact[m]%mod<<"\n";
return 0;
}
posted @   Sinktank  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2025-3-6 6:10:33 TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2024 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.
点击右上角即可分享
微信分享提示