列表

详情


NC22730. 小A的昆特牌

描述

小A最近迷上了一款叫做《巫师之昆特牌:王权的陨落》的游戏。在游戏中,小A需要操控一位失去了王位的女王Meve,四处打牌并夺回王位。
小A的牌库中有S张空白的牌,小A想把若干张牌锻造成步兵或者弩兵。而步兵牌的种类有n种,弩兵牌的种类有m种。小A希望部队能有足够的近战能力,又希望部队不会太过笨重。
所以他希望锻造成步兵的牌的数量大于等于l而小于等于r,他希望知道有多少种不同的锻造方法满足这个条件,由于这个数字很大,你需要输出对998244353取模后的结果。
两种锻造的方案不同,当且仅当锻造的牌的数量不同,或者步兵与弩兵的某一个种类的锻造的牌的数量不同。

输入描述

一行五个整数 n,m,S,l,r,含义如题目所示。

输出描述

一行一个整数,表示有多少种不同的锻造方案。

示例1

输入:

2 3 5 2 4

输出:

120

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1455ms, 内存消耗: 156880K, 提交时间: 2020-04-16 23:36:51

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int maxn=2e7+10;
int inv[maxn],A[maxn],B[maxn];
void init()
{
    inv[0]=inv[1]=1;
    for(int i=2;i<maxn;++i) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
    return;
}
int solve(int k,int n,int m,int S)
{
    if(k>=S) return 0;
    int ans=0;
    A[0]=1;
    for(int i=1;i<n;++i) A[i]=(ll)A[i-1]*(k+i)%mod*inv[i]%mod;
    B[n-1]=1;
    for(int i=m+1,j=S-k+m;i;--i,--j) B[n-1]=(ll)B[n-1]*j%mod*inv[i]%mod;
    for(int i=n-2;i>=0;--i) B[i]=(ll)B[i+1]*(S-k-1+n+m-i)%mod*inv[n+m-i]%mod;
    for(int i=0;i<n;++i){
        ans+=(ll)A[i]*B[i]%mod;
        if(ans>=mod) ans-=mod;
    }
    return ans;
}
int main()
{
    init();
    int n,m,S,l,r;
    scanf("%d%d%d%d%d",&n,&m,&S,&l,&r);
    printf("%d\n",(solve(l-1,n,m,S)-solve(r,n,m,S)+mod)%mod);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 1822ms, 内存消耗: 195984K, 提交时间: 2019-03-16 19:31:08

#include<iostream>
using namespace std;
const int N=2e7+10,mod=998244353;
int n,m,s,l,r,inv[N],A[N],B[N];
int calc(int p)
{
	if(p>s) return 0;int res=0;
	for(int i=A[0]=1;i<n;i++)
		A[i]=1ll*A[i-1]*(p-1+i)%mod*inv[i]%mod;
	for(int i=B[0]=1;i<=n+m;i++)
		B[i]=1ll*B[i-1]*(s-p+i)%mod*inv[i]%mod;
	for(int i=0;i<n;i++) (res+=1ll*A[i]*B[n+m-i]%mod)%=mod;
	return res;
}
int main()
{
	cin>>n>>m>>s>>l>>r;inv[1]=1;
	for(int i=2;i<N;i++) inv[i]=mod-1ll*mod/i*inv[mod%i]%mod;
	cout<<(calc(l)-calc(r+1)+mod)%mod<<endl;
}

上一题