AtCoder Beginner Contest 167 E Colorful Blocks 快速幂+阶乘逆元+组合数计算+隔板法

AtCoder Beginner Contest 167   比赛人数11940  比赛开始后15分钟看到A题,之后每隔一分钟,看到一道题,在比赛开始后第21分钟看到所有题

AtCoder Beginner Contest 167  E  Colorful Blocks  快速幂+阶乘逆元+组合数计算+隔板法

总目录详见https://blog.csdn.net/mrcrack/article/details/104454762

在线测评地址https://atcoder.jp/contests/abc167/tasks/abc167_e

OOOOO

0个相邻的块同色的情况如下

O|O|O|O|O   4个位置插入4个隔板,C(n-1,4)

只有1个相邻的块同色的情况如下

O|O|O|OO   4个位置插入3个隔板,C(n-1,3)  

只有2个相邻的块同色的情况如下

O|O|OOO   4个位置插入2个隔板,C(n-1,2)  

只有3个相邻的块同色的情况如下

O|OOOO   4个位置插入1个隔板,C(n-1,1) 

只有4个相邻的块同色的情况如下

OOOOO   4个位置插入0个隔板,C(n-1,0) 

样例模拟如下

3 2 1
2

3 2 1
6

3 2 2
8

8种组合如下
111
112
121
122
211
212
221
222

0个相邻的块同色的情况如下(2个间隔,插入2个隔板)
121
212
计算如下:
位置          1 2 3
可选择颜色数量 2 1 1  根据乘法原理,种类是2*1*1=2

解释如下:
位置1有2种颜色可选,
位置2与位置1不同色,故有2-1=1种颜色可选
位置3与位置2不同色,故有2-1=1种颜色可选
根据乘法原理,种类是2*1*1=2

写成公式如下:
位置1有m种颜色可选,
位置2与位置1不同色,故有m-1=m-1种颜色可选
位置3与位置2不同色,故有m-1=m-1种颜色可选
根据乘法原理,种类是
C(n-1,n-1)*m*(m-1)*(m-1)=C((n-1,n-1)*m*(m-1)^2=C((n-1,n-1)*m*(m-1)^(n-1)

   

只有2个相邻的块同色的情况如下(2个间隔,插入1个隔板)
112
122
221
222
计算如下:
位置          1 2 3
可选位置1,2为同色块,或者位置2,3为同色块,有2种选择
每个相邻同色块颜色有2种选择
剩下的另一个位置,因与同色块颜色不同,有2-1=1种选择
根据乘法原理,种类是2*2*1=4
总的总类是C(n-1,n-1-1)*m*(m-1)^(n-1-1)


3个相邻同色的情况如下(2个间隔,插入0个隔板)
111
222
计算如下:
位置          1 2 3
可选位置1,2,3为同色块,有1种选择
每个相邻同色块颜色有2种选择
根据乘法原理,种类是1*2=2
总的总类是C(n-1,n-1-2)*m*(m-1)^(n-1-2)

明白手工计算过程后,如何编写,就看个人了。

AC代码如下

#include <cstdio>
#include <algorithm>
#define mod 998244353
#define maxn 200010
#define LL long long
using namespace std;
LL fact[maxn],inv[maxn],ans,t[maxn],p;
int n,m,k,nm;
LL quick_pow(LL a,LL b){//a^b
	LL ans=1;
	while(b){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans%mod;
}
void init(){
	int i;
	scanf("%d%d%d",&n,&m,&k);
	nm=n,nm=max(nm,m),fact[0]=1;
	for(i=1;i<=nm;i++)fact[i]=fact[i-1]*i%mod;//fact[i]代表i!
	inv[nm]=quick_pow(fact[nm],mod-2);
	for(i=nm-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;//inv[i]代表i!的乘法逆元
}
LL C(LL a,LL b){//组合数计算
	return fact[a]*inv[a-b]%mod*inv[b]%mod;
}
int main(){
	int i;
	init();
	ans=0,p=quick_pow(m-1,n-k-1);
	for(i=n-k;i<=n;i++){
		ans=(ans+m*p%mod*C(n-1,i-1)%mod)%mod;//C(n-1,i-1)隔板法
		p=p*(m-1)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

类似的题目

洛谷 P3197 [HNOI2008]越狱

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值