专栏文章

题解:CF183D T-shirt

CF183D题解参与者 2已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@mipjfvx6
此快照首次捕获于
2025/12/03 13:00
3 个月前
此快照最后确认于
2025/12/03 13:00
3 个月前
查看原文
UPD 2025.4.22:修了一个唐爆了的锅。
首先考虑一个暴力 dp:
fi,j,kf_{i,j,k} 表示前 jj 个选了 kk 个颜色为 ii 的,显然有转移 fi,j,k=fi,j1,k(1pj,i)+fi,j1,k1pj,if_{i,j,k}=f_{i,j-1,k}(1-p_{j,i})+f_{i,j-1,k-1}p_{j,i}
gi,jg_{i,j} 表示带了 jj 件颜色为 ii 的衣服的期望人数,容易想到 gi,j=k=0jkfi,n,k+ik=j+1nfi,n,kg_{i,j}=\sum\limits_{k=0}^{j} kf_{i,n,k}+i\sum\limits_{k=j+1}^n f_{i,n,k}
时间复杂度 O(n2m)O(n^2m)

考察 gg 的变化量:
gi,j+1gi,j=k=j+1nfi,n,k=1k=0jfi,n,kg_{i,j+1}-g_{i,j}=\sum\limits_{k=j+1}^n f_{i,n,k}=1-\sum\limits_{k=0}^j f_{i,n,k}
容易想到 Δg\Delta g 是单调不增的。
根据期望的线性性,我们把它拆成每件衣服的贡献和后,贪心地取最大的 Δg\Delta g 一定是最优的,因为它一定不会因为取的数目的增加而导致有其它的贡献比它更大。
容易想到这样以后显然可以增加在一个颜色取的数量之后计算 fi,_,j+1f_{i,\_,j+1} 然后更新 Δg\Delta g,这样单次更新是 O(n)O(n) 的,一共取 nn 次,所以时间复杂度是 O(n2)O(n^2) 的。
总时间复杂度 O(n(n+m))O(n(n+m))
CPP
#include<bits/stdc++.h>
#define int long long
#define double long double
#define endl '\n'
using namespace std;
const int N=3005,M=305;
int n,m;
double p[3005][305],f[2][M][N],delta[M],ans;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;++i) for(int j=1,P;j<=m;++j) cin>>P,p[i][j]=P/1000.0;
	for(int i=1;i<=m;++i){
		f[0][i][0]=1;
		for(int j=1;j<=n;++j) f[0][i][j]=f[0][i][j-1]*(1-p[j][i]);
		delta[i]=1-f[0][i][n];
	}
	for(int i=1;i<=n;++i){
		int pos=1;
		for(int j=1;j<=m;++j) if(delta[j]>delta[pos]) pos=j;
		ans+=delta[pos];
		for(int j=1;j<=n;++j) f[1][pos][j]=f[1][pos][j-1]*(1-p[j][pos])+f[0][pos][j-1]*(p[j][pos]);
		delta[pos]-=f[1][pos][n];
		memcpy(f[0][pos],f[1][pos],sizeof(f[0][pos]));
	}
	cout<<fixed<<setprecision(10)<<ans<<endl;
	return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...