P3673 小清新计数题

又是一道A不掉的题,怪就怪洛谷的题解实在是太短(cha)了。

尽管如此,这个题解还是要膜的。


(From  https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P3673 )

求g[i][j]需要矩阵,然而我不会,所以这题只能扔掉了。

然后考虑f[i][j]:rep(i,1,n0)rep(j,1,n1)for(i1=0;i1<=i;i1+=2)rep(j1,0,j)if(i1||j1)f[i][j]+=C(i1+j1,i1)*C(i+j-i1-j1,i-i1)*g[i1+j1][i+j-i1-j1];

将计算的答案设为h[黑边数][白边数],可用背包解决,即rep(i,1,n0)rep(j,1,n1)per(i1,n0,i)per(j1,n1,j)h[i1][j1]+=h[i1-i][j1-j]*f[i][j];

下面的代码还没调过,是会爆零的。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define db double
#define mkp(x,y) make_pair(x,y)
#define pll pair<ll,ll>
#define X first
#define Y second
const ll N=51,MOD=998244353;
ll n,n1,n0,g[N][N],C[N][N],f[N][N],h[N][N];char s[N];
ll add(ll x,ll y){
	ll z=x+y;
	if(z>MOD)z-=MOD;
	return z;
}
ll mul(ll x,ll y){
	return x*y%MOD;
}
int main(){
	ll i,j,i1,j1;
	scanf("%s",s);n=strlen(s);
	rep(i,1,n)n1+=s[i]=='1';n0=n-n1;
	g[1][0]=1;rep(j,1,n)g[1][j]=mul(g[1][j-1],2*j-1);
	rep(j,1,n)g[1][j]=mul(g[1][j],j+1);
	rep(i,2,n){
		g[i][0]=mul(g[i-1][0],i);rep(j,1,n)
			g[i][j]=add(mul(g[i][j-1],i+j+j-2),mul(g[i-1][j],i-1));
	}
	rep(i,0,n)C[i][0]=1;
	rep(i,1,n)rep(j,1,n)C[i][j]=add(C[i-1][j-1],C[i-1][j]);
	rep(i,0,n0)rep(j,0,n1)for(i1=0;i1<=i;i1+=2)rep(j1,0,j)if(i1||j1)
		f[i][j]=add(f[i][j],mul(mul(C[i1+j1][i1],C[i+j-i1-j1][i-i1]),g[i1+j1][i+j-i1-j1]));
	rep(i,1,n0)rep(j,1,n1)per(i1,n0,1)per(j1,n1,j)
		h[i1][j1]=add(h[i1][1],mul(h[i1-i][j1-j],f[i][j]));
	printf("%lld\n",h[n0][n1]);
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值