洛谷卡特兰数
作者:互联网
卡特兰数
部分资料来源于https://www.bilibili.com/video/av96018454
引入
有m+n个人站成一排要进入剧院,门票是50元。其中有n个人有整50元,而m个人只有一张整100元。售票处一开始没有零钱,这些人需要以某种方式排队,使得售票处总有零钱可找,求可行方案数。
基本模型
给定n个0,m个1
问有多少序列,满足:
(1)n个0,m个1完全被使用
(2)对于任意前k个数,1的个数不少于0
理论
我们应该将问题转换成如下的东西处理:
如图,从左下出发,到右上结束,约束条件(1)中0和1数量就转换成了图中的横竖边数
而约束条件(2)的实现,无非就是路径选择上不能越过如图白色斜线
处理问题的方法
(1)DP
数据规模比较小的情况下,可以采用DP的思想,降空间复杂度可以掏个滚动数组。
(2)折线法
显然如图,只要与蓝线有交点的线,它就是不满足条件的线。
那么我们去研究符合条件的路径无非就是用总的路径数减去不符合条件的路径
我们把某条不合法路径A->C->B与蓝线的首个交点记为C。我们把左下角为A、右上角为蓝线末端的矩形以蓝线为对称轴对称过去,那么我们就可以得到宽为(m-1)长为(n+1)的一个矩形
把所有非法路径与蓝线首次相交的点一下镜像对称过去,如A->C->B也就成了A'->C->B,显然它穿过蓝线。
我们先看一下新矩阵,任意一条从A'->B的路径,它一定会穿过蓝线,也就是说,新矩形上选取的任意路径对应的原镜像路径都是非法的。
而又由于非法路径上的非法交点一定是在我们镜像的矩阵内,并且只要路径与蓝线有交点(无论多少个),它的起点到它的首个非法点之间就能形成镜像路径,并且与它后面的路径能够"无缝"衔接这条镜像路径,所以说明原图上所有非法路径均能在新矩阵上形成一条非重叠的新路径。
由此,我们可得,原图非法路径与新图非法路径是一一匹配的。
那么非法路径的数量也就引刃而解了。
P1641 [SCOI2010]生成字符串 逆元+卡特兰数
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
#define INF 1e10+5
#define maxn 105
#define minn -105
#define ld long double;
#define uint unsigned int;
#define ull unsigned long long;
typedef long long ll;
const ll mo=20100403;
ll min(ll a,ll b)
{
return a<b?a:b;
}
ll faspow(ll a,ll pow)
{
ll ans=1;
while(pow)
{
if(pow&1)ans*=a,ans%=mo;
a=a*a%mo;
pow>>=1;
}
return ans;
}
ll inver(ll a)
{
if(a==1)return 1;
return faspow(a,mo-2)%mo;
}
ll cal(ll n,ll m)
{
ll ans=1;
for(int i=1;i<=m;i++)
ans=ans*(n+1-i)%mo*inver(i)%mo;
return ans;
}
int main()
{
cin.tie(0);
cout.tie(0);
ios_base::sync_with_stdio(false);
ll n,m;
cin>>n>>m;
if(n<m)
{
cout<<0<<endl;
return 0;
}
ll ans=0;
ans=cal(n+m,m)%mo-cal(m+n,m-1)%mo+mo;
cout<<ans%mo<<endl;
return 0;
}
洛谷P2532 [AHOI2012]树屋阶梯 高精 卡特兰
标签:洛谷,蓝线,路径,非法,long,卡特兰,ll,define 来源: https://www.cnblogs.com/et3-tsy/p/12499286.html