牛客寒假训练营——买瓜

题意

智乃来到水果摊前买瓜,水果摊上贩卖着N个不同的西瓜,第i个西瓜的重量为wi。智乃对于每个瓜都可以选择买一个整瓜或者把瓜劈开买半个瓜,半个瓜的重量为wi/2。

也就是说对于每个西瓜,智乃都有三种不同的决策:

  1. 购买一整个重量为wi​的西瓜
  2. 把瓜劈开,购买半个重量为wi​​/2的西瓜
  3. 不进行购买操作

为了简化题目,我们保证所有瓜的重量都是一个正偶数。

现在智乃想要知道,如果他想要购买西瓜的重量和分别为k=1,2,3...M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对10^9+7取余数后的结果。

输入描述:

第一行输入两个整数N,M(0≤N≤10^3,1≤M≤10^3),分别表示西瓜的数目N,以及查询的重量上限为M。

若N不为0,接下来一行N个正偶数表示每个西瓜的重量。

输出描述:

输出一行M个数字,分别表示购买西瓜的重量和为k=1,2,3...M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对109+7取余数后的结果。

思路

这题可以用dp的来解,建立一个二维数组,dp[x][y]的含义理解成在轮到第x个西瓜以后,能购买到y重量的情况有多少种。所以在每次循环的时候,要把dp[i][wi]和dp[i][wi/2]置为1,来表示前面的西瓜全部不买,这个西瓜可以给wi和wi/2提供一个方案。接着就是把上一层的方案数量先继承下来,再对上一层的每一个重量情况加wi或者wi/2为下一个数组对与上个重量加wi或者wi/2的情况增添方案数。

代码

#include<bits/stdc++.h>
using namespace std;
const int M=1e9+7;
const int maxn=2*1e3+10;
long long dp[maxn][maxn];
int main()
{
    memset(dp,0,sizeof(dp));
    int x=1;
    int n,m;cin>>n>>m;
    int tmpn=n;
    while(tmpn--)
    {
        int w;cin>>w;
        dp[x][w]=1;
        dp[x][w/2]=1;
        for(int i=1;i<=m;i++)
        {
            dp[x][i]=(dp[x][i]+dp[x-1][i])%M;
            if(i>=w/2)
                dp[x][i]=(dp[x-1][i-w/2]+dp[x][i])%M;
            if(i>=w)
                dp[x][i]=(dp[x-1][i-w]+dp[x][i])%M;
        }
        x++;
    }
    for(int i=1;i<=m;i++)
       cout<<dp[n][i]<<" ";
    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值