1 条题解

  • 0
    @ 2026-6-1 10:43:29

    题意

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

    思路

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

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

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

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

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

    $$dp_{i,j} \gets dp_{i-1,j} \times f_{j-1,0} \times f_{m-j,0}$$

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

    $$dp_{i,j} \gets dp_{i-1,j-1} \times f_{j-1,1} \times f_{m-j,0}$$

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

    $$dp_{i,j} \gets dp_{i-1,j+1} \times f_{j-1,0} \times f_{m-j,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;
    } 
    
    
    • 1

    信息

    ID
    11607
    时间
    2000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    22
    已通过
    1
    上传者