• 美味糖果[一道简单的DP]


    I. 试题I:美味糖果 25'

    描述

    由于疫情缘故,wlxsq家里还剩下超多年货,没有吃完。

    为了简化问题,假设wlxsq家里还剩N种年货,每种年货Ai包,同一种年货中每一包都是一样的。

    现在wlxsq准备返杭了,他想从N种年货中挑不超过K包年货带返杭。wlxsq想知道他总共有多少种选择方案?

    输入

    第一行输入两个整数N,K,含义如题目描述。

    第二含输入N个整数 Ai,表示每一种年货的数量。

    输出

    输出总共方案数,结果对998244353取模。

    样例

    输入

    3 1
    2 2 2
    

    输出

    4

    输入

    8 13
    1 2 3 4 5 6 7 8
    

    输出

    65044

    提示

    【样例1解释】

    总共有4种方案,对应每一种年货的选择如下:(1,0,0),(0,1,0),(0,0,1),(0,0,0)

    【评测用例规模与约定】

    对于40%的数据,2<=N<=10,

    对于100%的数据,2<=N<=1000,Ai,K<=10^5

    题解

    1、$dp[i][j]$:前i种年货取j包的方案数

    2、$dp[i][j] = sum_{k = 0}^{Ai} dp[i - 1][j - k], j >= k$

    最后计算 $sum_{j = 0}^{K}dp[n][j]$即可
    优化1:使用滚动数组,保证内存不炸~

    优化2:使用前缀和,计算出$sum_{k = 0}^{Ai} dp[i - 1][j - k]$的值。

    #include<iostream>
    using namespace std;
    const int N=1e5+5;
    const int mod=998244353;
    int n,now,K,ans,a[N],f[2][N],s[2][N];
    int main(){
        scanf("%d%d",&n,&K);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        for(int i=0;i<=K;i++) s[0][i]=1;
        f[0][0]=1;
        for(int i=1;i<=n;i++){
            now^=1;
            for(int j=0,t;j<=K;j++){
                t=max(j-a[i]-1,-1);
                f[now][j]=(s[now^1][j]-(~t?s[now^1][t]:0)+mod)%mod;
                s[now][j]=((j?s[now][j-1]:0)+f[now][j])%mod;
            }
        }
        for(int j=0;j<=K;j++) (ans+=f[now][j])%=mod;
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    How to build and run ARM Linux on QEMU from scratch
    How to debug Android Native Application with eclipse
  • 原文地址:https://www.cnblogs.com/shenben/p/12294341.html
Copyright © 2020-2023  润新知