2019牛客暑假多校训练赛第八场 J Just Jump(思维dp)

题目链接:https://ac.nowcoder.com/acm/contest/888/J

 

题意:有一只青蛙在0位置处,他想跳到L位置处,但是路上会受到一些攻击,这只青蛙在出发前就知道自己在跳第几次的时间时哪一个位置会受到攻击,并且青蛙每次跳的距离要大于等于d,问青蛙安全(不受一次攻击)跳到L处的方案数

数据范围:1≤d≤L≤1e7,1≤t,p<L,1≤m≤3000,mod=998244353;

 

思路:首先不考虑受攻击的情况,那么可以用一个dp和前缀和算出所有情况dp[i]=sum[i-d],sum[i]=sum[i-1]+dp[i].然后考虑受到一次攻击的情况就是对于每个受攻击的位置,正好第ti步跳到那里受到攻击那么情况数C\binom{ti-1}{pi-d*ti+ti-1}*dp[L-pi],那么只需要容斥一下,减去一次受到攻击的次数,加上两次受到攻击的次数,减去三次受到攻击的次数。。。。。这个可以通过对pi排序暴力容斥一下。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+10;
const int mod=998244353;
int n,m,t,L,d,b[N],dp[N],sum[N],fac[N],facv[N];
pair<int,int>a[3005];
int quickpow(ll a,ll b){
     int ans=1;
     a%=mod;
     while(b){
        if(b&1)ans=1ll*ans*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
     }
     return ans%mod;
}
void init(){
    fac[0]=facv[0]=1;
    for(int i=1;i<N;i++)fac[i]=1ll*fac[i-1]*i%mod;
    facv[N-1]=quickpow(fac[N-1],mod-2);
    for (int i=N-1;i;i--)facv[i-1]=1ll*facv[i]*i%mod;
}
int C(int x,int y){
    if(x<y) return 0;
    return 1ll*fac[x]*facv[y]%mod*facv[x-y]%mod;
}
int solve(int l,int r){
    if(a[l].second>=a[r].second||a[l].first==a[r].first)return 0;
    int len=a[r].first-a[l].first,tm=a[r].second-a[l].second;
    if (1ll*tm*d-len>0) return 0;
    return C(len-tm*d+tm-1,tm-1);
}
int main(){
    init();
    scanf("%d%d%d",&L,&d,&m);
    for(int i=1;i<=m;i++)scanf("%d%d",&a[i].second,&a[i].first);
    sort(a+1,a+m+1);
    sum[0]=b[0]=1;
    for(int i=1;i<d;i++)sum[i]=sum[i-1];
    for(int i=d;i<=L;i++){
        dp[i]=sum[i-d];
        sum[i]=(sum[i-1]+dp[i])%mod;
    }
    for(int i=1;i<=m;i++){
        for(int j=0;j<i;j++)b[i]=(b[i]+1ll*b[j]*solve(j,i)%mod)%mod;
        b[i]=(mod-b[i])%mod;
    }
    for(int i=1;i<=m;i++)dp[L]=(dp[L]+1ll*b[i]*dp[L-a[i].first]%mod)%mod;
    printf("%d\n",dp[L]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值