【模拟7.27】题(liu_runda的神题)(卡特兰数,组合数)

考场的SB经验不再分享

case 0:

一道组合计数的水题,具体不再讲可以看以前的相似题

case 1:

很明显的卡特兰计数,我们把长度为n的序列看成01串

关于卡特兰计数的详细的讲解

由此可知我们需要满足从1——n中前缀1的数量不少于前缀0的数量

case 2:

满足可以在坐标轴上移动

设f[i]表示第i步回到原点,我们枚举第j步第一次回到起点

那么f[i]数组里就不会出现重复,这样可以保证正确性

同时要再次用到卡特兰数:

   我们发现定义的特殊j是第一次回到起点,但cal中可以多次回到起点

但我们可以发现只要我们满足在1-j-1满足前缀和>=1即可,这样我们可以

发现现在序列一部分确定设正方向为1

    1 1 .........0 0

这样中间部分就又是一个cal,这样我们直接乘cal(j/2-1)即可

(注意可能j是四个方向,于是乘4)

case 3:

同时在两轴及第一象限

直接用组合数,乘两个方向的cal即可

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<stack>
 8 #include<map>
 9 #include<queue>
10 #define ps push_back
11 #define MAXN 1000001
12 #define ll long long
13 using namespace std;
14 ll n;
15 const ll mod=1000000007;
16 ll jie[MAXN],ni[MAXN],ni_c[MAXN];
17 ll C(ll x,ll y)
18 {
19     if(y>x)return 0;
20     return jie[x]*ni_c[y]%mod*ni_c[x-y]%mod;
21 }
22 ll cal(ll x)
23 {
24      return C(x*2,x)*ni[x+1]%mod;
25 }
26 ll f[MAXN];
27 int main()
28 {
29       ll orz;
30       scanf("%lld%lld",&n,&orz);
31       jie[0]=1;jie[1]=1;
32       ni[0]=1;ni[1]=1;
33       ni_c[0]=1;ni_c[1]=1;
34       for(ll i=2;i<=2*n+10;++i)
35       {
36          jie[i]=(jie[i-1]*i)%mod;
37          ni[i]=((mod-mod/i)*ni[mod%i])%mod;
38          ni_c[i]=(ni_c[i-1]*ni[i])%mod;
39       }
40       ll ans=0;
41       if(orz==0)
42       {
43           for(ll i=0;i<=n;i+=2)
44           {
45                ans=(ans+C(n,i)*C(i,i/2)%mod*C(n-i,(n-i)/2))%mod;
46           }
47           printf("%lld\n",ans%mod);
48       }
49       else if(orz==1)
50       {
51           if(n%2==1)
52                printf("0\n");
53           else
54                printf("%lld\n",(C(n,n/2)%mod*ni[n/2+1]%mod+mod)%mod);
55       }
56       else if(orz==3)
57       {
58           for(ll i=0;i<=n;i+=2)
59           {
60                ll th=C(n,i);
61                if((n-i)%2==1)continue;
62                ans=(ans+th*cal(i/2)%mod*cal((n-i)/2))%mod;
63           }     
64           printf("%lld\n",ans);
65       }
66       else if(orz==2)
67       {
68            f[0]=1;
69            for(ll i=2;i<=n;i+=2)
70            {
71                for(ll j=0;j<=i;j+=2)
72                {
73                     f[i]=(f[i]+4*f[i-j]*cal(j/2-1))%mod;
74                }
75            }
76            printf("%lld\n",f[n]);
77       }
78 }
View Code

 

posted @ 2019-07-27 15:29  Wwb_star  阅读(219)  评论(0编辑  收藏  举报