游戏

题目描述

九条可怜最近在玩一个大型无双游戏。  在游戏的数据库中,有 n 个敌人,每一个敌人有两个属性,血量 hi 和攻击力 ai。每一关游戏中,游戏会从数据库中随机选出若干个敌人(至少一个)来形成关卡。显然一共有 2n-1 种不同的游戏。  因为这时一个无双游戏,因此可怜有无限的血量和 imba 的攻击方式:当可怜每按一次攻击键,都会对所有敌人产生 1 点伤害(血量减一)。  当一个敌人在血量小于等于 0 的时候会发动自爆,它会对场上所有还存活的单位造成 ai 的伤害(同时死亡则同时自爆)。因为可怜的血量是无限的,所以自爆的唯一作用就是帮助可怜攻击场上还存活的敌人。  举例来说,如果有四个敌人,血量分别为 1,1,4,7,攻击力分别为 2,2,1,1。则可怜在攻击一次之后,会产生以下的连锁反应:  1. 敌人的血量降为 0,0,3,6,前两个敌人同时发动自爆。 2. 敌人的血量降为 0,0,-1,2,第三个敌人发动自爆。 3. 敌人的血量降为 0,0,-1,1,连锁反应结束。  我们可以假设敌人的自爆是在瞬间完成的,即可怜在按下攻击键之前,之前的所有攻击引发的自爆以及连锁反应都已经结束了。  显然不管游戏怎么样,只要可怜攻击足够多次,她都能消灭所有敌人。但是可怜是一个懒惰的女孩子,她想要知道在所有的 2n-1 种可能的游戏中,在 K 次攻击内就能消灭所有敌人的有多少种。

输入描述:

输入一行两个整数 n,K。第二行 n 个整数 hi 表示血量。第三行 n 个整数 ai 表示攻击力。对于  的数据,n ≤ 20。对于  的数据,n ≤ 100, hi,ai,K ≤ 1000。对于  的数据,1 ≤ n ≤ 1000, 1 ≤ hi,ai, K ≤ 105。

输出描述:

输出一行一个整数表示答案,答案可能很大,对 998244353 取模后输出。

示例1

输入

4 1
1 1 4 7
2 2 1 1

输出

4

思路

敌人肯定会按照血量顺序死亡的,所以把所有敌人按照血量升序排序
第 i 个敌人会受到 K+sum{j < i} a[j] 点伤害,这个敌人会死亡当只会在这个数值大于等于 h[i]
dp[i][j],表示当前考虑了前 i 个敌人,所有加入游戏的敌人的攻击力的和为j

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
const int mod=998244353;
struct node
{
    int a,h;
}p[maxn];
int n,k,dp[maxn];
bool cmp(node x,node y)
{
    return x.h<y.h;
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) 
  scanf("%d",&p[i].h);
    for(int i=1;i<=n;i++) 
  scanf("%d",&p[i].a);
    sort(p+1,p+1+n,cmp);
    dp[0]=1;
    for(int i=1;i<=n;i++)
 {
        for(int j=100000;j>=0;j--)
  {
            if(j+k>=p[i].h)
   {
                int ans=min(100000,j+p[i].a);
                dp[ans]+=dp[j];
                dp[ans]%=mod;
            }
        }
    }
    int sum=0;
    for(int i=1;i<=100000;i++)
 {
        sum+=dp[i];
        sum%=mod;
    }
    printf("%d\n",sum);
    return 0;
}

来源:nkw

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值