icpc网络赛第二场K Meal

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了icpc网络赛第二场K Meal相关的知识,希望对你有一定的参考价值。

icpc网络赛第二场K Meal

题意:

有n个人,n个菜,
现在n个人轮流吃菜,起初S中有n个菜,第i个人会在还没拿走的菜中随机选一个,拿走第j个菜的概率为 a i , j ∑ k ∈ S a i , k \\frac{a_{i,j}}{\\sum_{k∈S}a_{i,k}} kSai,kai,j,然后将这个菜从集合S中删除,如果S为空则结束,否则轮到下一个继续拿菜
让你输出第i个人拿第j个菜的概率
n<=20 , a i , j a_{i,j} ai,j<=100

题解:

比赛时想好大体思路,好不容易把A写完,调了半天,最后没时间做K了
题意很好理解,对于不同的拿取方式,对于第i个人的情况是不同的,不难看出n很小才20,所以我们可以状压dp
我们枚举二进制,1表示这个菜被取了,0表示还未取
对于一个状态state,假设共cnt个位置为1,因为是顺序吃菜,所以就是求第cnt个人的吃菜概率,枚举其中为1的位置,相当于是吃的第j种菜
用f[i]表示当前这个选菜局面的概率,i的二进制状态下表示菜的选取情况
利用之前的f[]来转移现在的ans[][],用现在的选取状态来更新当前的f[]
这样得到转移方程:

ans[cnt][j]=(ans[cnt][j]+f[i^(1ll<<j)]*a[cnt][j]%mod*inv[sum[cnt]-tot+a[cnt][j]])%mod;
f[i]=(f[i]+f[i^(1ll<<j)]*a[cnt][j]%mod*inv[sum[cnt]-tot+a[cnt][j]])%mod;

这样复杂度为O(n*2n),注意因为a很小,所以求逆元不要用快速幂,会超时,直接O(n)预处理好即可

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
const int N=21;

int dp[N][1<<N];
int  a[N][N];
int f[1<<N];
int ans[N][N];
int sum[N];
int inv[30000000];
const int mod= 998244353;
int qmi(int a,int b)
{
	int res=1;
	while(b){
		if(b&1)	res=res*a%mod;
		b>>=1;
		a=a*a%mod;
	}
	return res;
}
void init(){
	inv[1]=1;
	for(int i=2;i<=2000;++i)
	  inv[i]=mod-(long long)mod/i*inv[mod%i]%mod;
}
signed main()
{
	int n;
	cin >> n;
	init();
	for(int i=1;i<=n;i++)	
	{
		for(int j=0;j<n;j++)	
		cin >> a[i][j],sum[i]=(sum[i]+a[i][j])%mod;
	}

	f[0]=1;
	for(int i=1;i<1<<n;i++){
		int cnt=0;
		int tot=0;
		for(int j=0;j<n;j++)
			if(i>>j&1)	cnt++;
		for(int j=0;j<n;j++)
			if(i>>j&1)	tot=(tot+a[cnt][j])%mod;
		for(int j=0;j<n;j++)
		{
			if(i>>j&1)
			{
//				cout<<"sum[cnt]-?tot+a[cnt][j]="<<sum[cnt]-tot+a[cnt][j]<<endl;
				ans[cnt][j]=(ans[cnt][j]+f[i^(1ll<<j)]*a[cnt][j]%mod*inv[sum[cnt]-tot+a[cnt][j]])%mod;
				
				f[i]=(f[i]+f[i^(1ll<<j)]*a[cnt][j]%mod*inv[sum[cnt]-tot+a[cnt][j]])%mod;
			}
		}	
//		cout<<f[i]<<endl;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<n;j++)
		if(j==0)
			cout<<ans[i][j];
		else 
		cout<<" "<<ans[i][j];
			cout<<endl;
	}
}


以上是关于icpc网络赛第二场K Meal的主要内容,如果未能解决你的问题,请参考以下文章

ICPC网络赛第二场G Limit

ICPC网络赛第二场G Limit

ICPC网络赛第二场 L.Euler Function 欧拉函数性质+势能线段树

ICPC网络赛第二场 L.Euler Function 欧拉函数性质+势能线段树

2021ICPC网络赛第二场The 2021 ICPC Asia Regionals Online Contest (II) L Euler Function

2021-icpc网络赛第二场-M.J.G.L(后续补题中)