codeforces Nauuo and Pictures

题目描述
题解

暴力永远不是题解的暴力

考虑暴力dp: f w [ i ] [ j ] [ k ] f_w[i][j][k] fw[i][j][k] 表示目前权值是 w w w w w w 是喜欢的,喜欢的和为 j j j ,不喜欢的为 k k k i i i 轮后的期望值, g w [ i ] [ j ] [ k ] g_w[i][j][k] gw[i][j][k] 是类似的,只是 w w w 是不喜欢的

考虑转移: f w [ i ] [ j ] [ k ] = w j + k × f w + 1 [ i − 1 ] [ j + 1 ] [ k ] + j − w j + k × f w [ i − 1 ] [ j + 1 ] [ k ] + k j + k × f w [ i − 1 ] [ j ] [ k − 1 ] f_w[i][j][k]=\frac{w}{j+k} \times f_{w+1}[i-1][j+1][k]+\frac{j-w}{j+k} \times f_w[i-1][j+1][k]+\frac{k}{j+k}\times f_w[i-1][j][k-1] fw[i][j][k]=j+kw×fw+1[i1][j+1][k]+j+kjw×fw[i1][j+1][k]+j+kk×fw[i1][j][k1]

然后我们可以证明 f w [ i ] [ j ] [ k ] = w f 1 [ i ] [ j ] [ k ] f_w[i][j][k]=wf_1[i][j][k] fw[i][j][k]=wf1[i][j][k] ,证明的话就用数学归纳法,就是 f w [ i − 1 ] [ j ] [ k ] = w f 1 [ i − 1 ] [ j ] [ k ] f_w[i-1][j][k]=wf_1[i-1][j][k] fw[i1][j][k]=wf1[i1][j][k] ,然后把式子化开就能证了

所以我们现在只需要求 f 1 [ i ] [ j ] [ k ] f_1[i][j][k] f1[i][j][k] ,同时我们发现 j , k j,k j,k 状态的加减次数和 m − i m-i mi 相同,所以我们可以设计dp: f [ i ] [ j ] f[i][j] f[i][j] 表示喜欢的被选了几次,不喜欢的被选了几次,当前权值为 1 1 1 ,在 m − j − k m-j-k mjk 轮后的期望值,然后和上面的转移类似,可以预处理逆元将效率达到 O ( n + m l o g P + m 2 ) O(n+mlogP+m^2) O(n+mlogP+m2)

代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5,M=3005,P=998244353;
int n,m,a[N],b[N],w[N],c[2],f[M][M],g[M][M];
int K(int x,int y){
	int z=1;
	for (;y;y>>=1,x=1ll*x*x%P)
		if (y&1) z=1ll*z*x%P;
	return z;
}
int main(){
	cin>>n>>m;
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for (int i=1;i<=n;i++)
		scanf("%d",&w[i]),c[a[i]]+=w[i];
	for (int i=max(m-c[0]-c[1],0);i<=m+m;i++)
		b[i]=K(c[0]+c[1]+i-m,P-2);
	for (int i=m;~i;i--){
		f[i][m-i]=g[i][m-i]=1;
		for (int j=min(m-i-1,c[0]);~j;j--)
			f[i][j]=1ll*(1ll*(c[1]+i+1)*f[i+1][j]%P+1ll*(c[0]-j)*f[i][j+1]%P)*b[i-j+m]%P,
			g[i][j]=1ll*(1ll*(c[1]+i)*g[i+1][j]%P+1ll*(c[0]-j-1)*g[i][j+1]%P)*b[i-j+m]%P;
	}
	for (int i=1;i<=n;i++)
		printf("%lld\n",1ll*w[i]*(a[i]?f[0][0]:g[0][0])%P);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值