题解:P17224 [Math×Girl²] 搬家
下文表示物品数和容量的
首先我们发现,价值为
设有
若
若
-
若
n-k\le h ,此时所有物品都能装进去,可以随便分,方案数为\binom nk 。 -
若
n-k>h ,此时应该装入k 个1 和h 个该装的2 。-
若
(m-k)\bmod2=1 ,所有的不该装的2 必须在最后,k 个1 和h 个2 可以任意排列,方案数为\binom{k+h}k 。 -
若
(m-k)\bmod2=0 ,除了上面的方案,还可以先放k-1 个1 和h 个该装的2 ,再在剩下的n-k-h 个不该装的2 中放一个1 (剩余容量为1 ,不会装入2 ),方案数为\binom{k+h-1}{k-1}\times(n-k-h) 。
-
预处理阶乘及其逆元后按照上面的式子计算即可,时间复杂度
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int mod=998244353;
inline ll qpow(ll a,ll b){
ll res=1;
for (;b;b>>=1,a=a*a%mod) if (b&1) res=res*a%mod;
return res;
}
ll inv[10000001],fac[10000001],ifac[10000001];
inline ll C(int n,int m){
if (n<0 or n<0 or n<m) return 0;
return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,m;
cin>>n>>m;
inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for (int i=2;i<=n;i++){
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
fac[i]=fac[i-1]*i%mod;
ifac[i]=ifac[i-1]*inv[i]%mod;
}
ll ans=0;
if (n>=m) ans=(qpow(2,n-m+1)-1+mod)%mod;
for (int i=0;i<=min(n,m-1);i++){
int h=(m-i)>>1;
if (n-i<=h) ans=(ans+C(n,i))%mod;
else{
ans=(ans+C(i+h,i))%mod;
if (((m-i)&1)==0){
if (i) ans=(ans+C(i+h-1,i-1)*(n-i-h))%mod;
}
}
}
cout<<ans;
return 0;
}