zoukankan      html  css  js  c++  java
  • 【CSP2019】Emiya 家今天的饭

    【CSP2019】Emiya 家今天的饭

    题意

    链接

    题解

    显然根据性质最多的菜品不超过总数量的一半,可以考虑补集转化

    即计算有一个菜品超过数量一半的方案数,再用总方案数减

    总方案数显然可以一个背包搞定(然而我去年就是因为总方案数没求对挂了)

    然后考虑求超过一半的方案数

    枚举当前哪个菜品是超过一半的

    有一个显然的DP:

    $ f_{i,j,k} $ 表示当前到第i行最多的菜品选了j个,其余的选了K个的方案数

    但是这样会T

    考虑能否优化

    注意到我们需要的状态并不需要知道菜品的具体数量,只需要要求菜品的相对数量关系

    于是可以枚举相对数量关系来压缩一维

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define LL long long 
    
    inline LL read()
    {
        LL x= 0,f = 1;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch <'0'||ch >'9');
        do
        {
            x = (x << 3) + (x << 1) + ch - '0';
            ch = getchar();
        }while(ch >= '0' && ch <= '9');
        return f*x;
    }
    
    const int MOD = 998244353;
    const int MAXN = 100 + 10;
    const int MAXM = 2000 + 10;
    
    int n,m;
    LL a[MAXN][MAXM];
    LL tot_meal;
    LL f[MAXN],s[MAXN];
    LL dp[MAXN][MAXN<<1];
    
    int main()
    {
    //    freopen("meal.in","r",stdin);
    //    freopen("meal.out","w",stdout);
        n = read(),m = read();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                a[i][j] = read();
                s[i] += a[i][j];s[i] %= MOD;
            }
        }
        f[0] = 1;
        for(int i=1;i<=n;i++)
            for(int j=i;j>=1;j--)
                f[j] = (f[j] + f[j-1] * s[i] % MOD) % MOD;
        for(int i=1;i<=n;i++) tot_meal += f[i] ,tot_meal %= MOD;
        //cout << tot_meal << endl;
        LL ans = tot_meal;
        for(register int cur=1;cur<=m;cur++)
        {
            memset(dp,0,sizeof(dp));
            dp[0][n] = 1;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n+i;j++)
                {
                    dp[i][j] = dp[i-1][j] % MOD;
                    (dp[i][j] += dp[i-1][j+1] * (s[i] - a[i][cur])) %= MOD;
                    (dp[i][j] += dp[i-1][j-1] * a[i][cur]) %= MOD;
                }
            }
            for(int j=n+1;j<=2*n;j++) ans = (ans - dp[n][j] + MOD) % MOD;
        }
        cout << ans << endl;
    }
  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/14013262.html
Copyright © 2011-2022 走看看