AtCoder Beginner Contest 167 E:Colorful Blocks 组合数/DP分析

Alanni ·
更新时间:2024-11-13
· 897 次阅读

我们先DP分析

dp[i][j]表示,按从左往右的顺序填到i时,有j对相邻数字不同,的方案数

显然:dp[i][j]=dp[i-1][j]*(m-1)+dp[i-1][j-1];

我们把DP在纸上推演如下:

发现:每个i所在行的d[pi][j]其实就是二次项展开的一项

dp[n][j]=m*C_{n-1}^j*(m-1)^{n-i-1}

求和dp[n][0]到dp[n][k]即可。

第二种思路是用组合数直接进行分析:

考虑:n个数,k个相邻位置数相同,

我们在n-1个空位中选择k个位置,使得k左右数相同。

然后固定最左边的数,有m种选法,依次往右选,遇到刚才选出的位置,选法只有一种。

其余都是m-1种选法。

综上方案数为:m*C_{n-1}^j*(m-1)^{n-i-1}

同样求和即可。

#include using namespace std; typedef long long ll; #define ls (o<<1) #define rs (o<>n>>m>>k; fac[0]=p[0]=inv[0]=1; for(int i=1;i<=200000;i++)fac[i]=fac[i-1]*i%mod,p[i]=p[i-1]*(m-1)%mod;; inv[200000]=qpow(fac[200000],mod-2); for(int i=200000-1;i;i--)inv[i]=inv[i+1]*(i+1)%mod; ll ans=0; for(int i=1;i<=k;i++) { ll C=fac[n-1]*inv[i]%mod*inv[n-1-i]%mod; ans=(ans+m*p[n-i-1]%mod*C%mod)%mod; } ans=(ans+m*p[n-1]%mod)%mod; cout<<ans<<endl; return 0; } 夕林山寸 原创文章 410获赞 22访问量 2万+ 关注 私信 展开阅读全文
作者:夕林山寸



dp contest 组合数 blocks

需要 登录 后方可回复, 如果你还没有账号请 注册新账号