题解:AT_abc113_d [ABC113D] Number of Amidakuji

题意

m m m 条竖线,每条线上有 n n n 个高度。从 ( 1 , 1 ) (1,1) (1,1) 出发,每次遇到横线时都选择经过它,并且不存在两条端点重合的横线,一条横线的两端点必须在同一高度,一条横线连接的需要是相邻的两条竖线。求从 ( 1 , 1 ) (1,1) (1,1) ( h , k ) (h,k) (h,k) 的图的方案数。

思路

考虑 d p dp dp,我们可以用 d p i , j dp_{i,j} dpi,j 表示从 ( 1 , 1 ) (1,1) (1,1) ( i , j ) (i,j) (i,j) 的方案数。

在此之前,我们需要先求一个东西,我们定义 f i , 0 f_{i,0} fi,0 为放到第 i i i 个位置不放边的方案数,定义 f i , 1 f_{i,1} fi,1 为放到第 i i i 个位置放边的方案数。不难想到:

f i , 0 ← f i − 1 , 0 + f i − 1 , 1 f_{i,0} \gets f_{i-1,0}+f_{i-1,1} fi,0fi1,0+fi1,1
f i , 1 ← f i − 1 , 0 f_{i,1} \gets f_{i-1,0} fi,1fi1,0

不难看出, ( i , j ) (i,j) (i,j) 可以由 ( i − 1 , j ) (i-1,j) (i1,j) ( i − 1 , j − 1 ) (i-1,j-1) (i1,j1) ( i − 1 , j + 1 ) (i-1,j+1) (i1,j+1) 到达,即一个点上面三个点。

首先,假如是要直接由上面的点移下来,就需要要求上面那个点左边和右边都没有边,所以可以推出:

d p i , j ← d p i − 1 , j × f j − 1 , 0 × f m − j , 0 dp_{i,j} \gets dp_{i-1,j} \times f_{j-1,0} \times f_{m-j,0} dpi,jdpi1,j×fj1,0×fmj,0

接下来,如果是由左上的点推出,就需要要求上面那个点左边有边,而右边都没有边,所以可以推出:

d p i , j ← d p i − 1 , j − 1 × f j − 1 , 1 × f m − j , 0 dp_{i,j} \gets dp_{i-1,j-1} \times f_{j-1,1} \times f_{m-j,0} dpi,jdpi1,j1×fj1,1×fmj,0

从右上的点推出的也同理。

d p i , j ← d p i − 1 , j + 1 × f j − 1 , 0 × f m − j , 1 dp_{i,j} \gets dp_{i-1,j+1} \times f_{j-1,0} \times f_{m-j,1} dpi,jdpi1,j+1×fj1,0×fmj,1

Code

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int mod=1000000007;
int n,m,k;
int f[105][2],dp[105][105];
signed main(){
	scanf("%lld%lld%lld",&n,&m,&k);
	f[0][0]=1;
	for(int i=1;i<=m;i++){
		f[i][0]=(f[i-1][0]+f[i-1][1])%mod;
		f[i][1]=f[i-1][0];
	}
	dp[0][1]=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			dp[i][j]=(dp[i][j]+((dp[i-1][j]*((f[j-1][0]*f[m-j][0])%mod)%mod)%mod))%mod;
			dp[i][j]=(dp[i][j]+((dp[i-1][j-1]*((f[j-1][1]*f[m-j][0])%mod)%mod)%mod))%mod;
			dp[i][j]=(dp[i][j]+((dp[i-1][j+1]*((f[j-1][0]*f[m-j][1])%mod)%mod)%mod))%mod;
		}
	printf("%lld\n",dp[n][k]);
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值