zoukankan      html  css  js  c++  java
  • CSP2019 Emiya 家今天的饭 题解

    这题在考场上只会O(n^3 m),拿了84分。。

    先讲84分,考虑容斥,用总方案减去不合法方案,也就是枚举每一种食材,求用它做超过(lfloor frac{k}{2} floor) 道菜的方案数,从总方案中减去。

    先枚举一种食材x,设f[i][j][k]为前i种烹饪方法中,做j道菜,其中k道是食材x做的的方案数,转移考虑第i种烹饪方案 不做菜/做食材x的菜/做其他食材的菜 三种情况。最后所有f[n][j][j/2+1 ~ n]的和即是不合法情况。

    考虑怎么优化,设一种方案中有k道菜,其中t道菜是x食材做的,那么当且仅当(t>lfloor frac{k}{2} floor)时方案不合法,也即(2t-k>0)时不合法。那么我们在dp时就只需要记录方案中(2t-k)的值,最后取大于0的状态的方案数即可。即设f[i][j]为只考虑前i种烹饪方法,方案中(2t-k)的值为j的方案数。转移考虑以上三种情况分别转移到 f[i+1][j]/f[i+1][j+1]/f[i+1][j-1] 即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 107
    #define M 2007
    #define ll long long
    const ll mod=998244353;
    ll a[N][M],sum[N],f[N][N<<1];
    int main()
    {
    	int n,m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%lld",&a[i][j]);
    			sum[i]=(sum[i]+a[i][j])%mod;
    		}
    	ll ans=0;
    	for(int now=1;now<=m;now++)
    	{
    		memset(f,0,sizeof(f));
    		f[0][N]=1;
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=N-n;j<=N+n;j++)
    			{
    				f[i][j]=(f[i][j]+f[i-1][j])%mod;
    				f[i][j]=(f[i][j]+f[i-1][j-1]*a[i][now])%mod;
    				f[i][j]=(f[i][j]+f[i-1][j+1]*(sum[i]+mod-a[i][now]))%mod;
    			}
    		}
    		for(int i=1;i<=n;i++)
    			ans=(ans+f[n][N+i])%mod;
    	}
    	ll res=1;
    	for(int i=1;i<=n;i++)
    		res=res*(sum[i]+1)%mod;
    	res=(res+mod-1)%mod;
    	res=(res+mod-ans)%mod;
    	printf("%lld
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    HDU 4325 Contest 3
    HDU 4324 Contest 3
    HDU 4323 Contest 3
    HDU 4321 Contest 3
    HDU 4320 Contest 3
    HDU 4314 Contest 2
    HDU 4313 Contest 2
    HDU 4318 Contest 2
    12-----简单认识下margin
    11-----broder(边框)
  • 原文地址:https://www.cnblogs.com/lishuyu2003/p/11891877.html
Copyright © 2011-2022 走看看