题解 AT3965-[AGC025B] RGB Coloring

(Large atural) AT3965 [AGC025B] RGB Coloring / 原题链接


思路

首先,明显地,我们可以把绿色看成同时涂上红色和蓝色。这样得分仍为 (A+B)

所以红色和蓝色就独立了,即它们互不影响(转化前是一个格子涂了红色就不能再涂蓝色,不是独立的)。

所以我们依次枚举红色的个数 (i),这样蓝色的个数就是 (j=frac{(K-A imes i)}{B})

然后用排列组合公式来枚举会有多少种方案。即 (C^i_n*C^j_n)

因为时间不紧,我用了快速幂求逆元。

代码

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define lon long long
using namespace std;
lon mo=998244353;
lon n,a,b,ned,ans,mul[312345];

lon power(lon p,lon q){
	lon tot=1;
	while(q){
		if(q&1)tot=(tot*p)%mo;
		p=(p*p)%mo;
		q=q>>1;
	}
	return tot;
}

lon inv(lon z){return power(z%mo,mo-2);}

lon Cnm(lon Cn,lon Cm){
	if(Cn<0 || Cn>n || Cm-Cn<0)return 0;
	lon upp=(mul[Cm]*inv(mul[Cm-Cn]))%mo,low=mul[Cn];
	return (upp*inv(low))%mo;
}

int main(){
	cin>>n>>a>>b>>ned;
	mul[0]=1;
	rep(i,1,n)mul[i]=(mul[i-1]*i)%mo;
	rep(i,0,n){
		if(ned-i*a<0)break;
		if((ned-i*a)%b==0)ans=(ans+Cnm(i,n)*Cnm( (ned-i*a)/b ,n)%mo)%mo;
	}
	cout<<ans;
}
原文地址:https://www.cnblogs.com/BlankAo/p/14004958.html