[Math×Girl²] 搬家
第
考虑什么时候打包机的方案不是最优的:打包机方案不是最优,即存在可以通过改变更大编号的选择使得较小的编号被选。这只能是打包机的方案恰好使得箱子容量剩余
下面考虑合法情况,分为两大类。
第一类:对于第一个未被选择的
- 若存在编号
\lt d 的物品大小为2 ,那么其必然被打包机选中,进而大小为1 的物品必然全被选中,于是编号\lt d 的物品全被选中且编号\gt d 的物品中大小为1 的物品全被选中; - 若不存在编号
\lt d 的物品大小为2 ,也即不存在大小为2 的物品被选中,这当且仅当M\le N 时可能发生。
对于这两种情况重新按照编号
第二类:若第一个未被选择的
- 所有物品大小均为
1 ; - 箱子足以容纳所有的物品。
当
对于第一类中所有编号
对于第二类中箱子足以容纳所有物品的情况,显然合法方案数共有
对于
- 前
M 个均为1 ,后面部分任意,这是对于第一类以及第二类的全部大小均为1 的补充,合计2^{N-M} 种; - 前
M-1 个中恰有一个为2 ,第M 个及以后均为2 ,这一部分原本应为第一部分i=M 时的情况中箱子容量剩余0 的子情况,合计M-1 种; - 前
M-1 个均为1 ,第M 个为2 ,后面部分任意,合计2^{N-M} 种。
这三种情况恰好能覆盖
同时对于
:::success[Code]
#include<bits/stdc++.h>
using namespace std;
long long frac[10000007],inv[10000007];
const long long mod=998244353,e7=1e7;
long long binom(long long n,long long m){
if(m>n||m<0)return 0;
return frac[n]*inv[m]%mod*inv[n-m]%mod;
}
long long quickpow(long long a,long long b){
long long ans=1;
long long base=a;
while(b){
if(b&1)ans*=base,ans%=mod;
base*=base,base%=mod;
b>>=1;
}
return ans;
}
long long ans=0,n,m;
int main(){
scanf("%lld%lld",&n,&m);
m=min(m,2*n);
frac[0]=inv[0]=1;
for(int i=1;i<=e7;++i) frac[i]=i*frac[i-1]%mod;
inv[e7]=quickpow(frac[e7],mod-2);
for(int i=e7-1;i>0;--i) inv[i]=inv[i+1]*(i+1)%mod;
int t=(m<n?m-2:n-1);
for(int i=0;i<=t;++i){//PART 1
long long tmp=binom(i,m-1-i)*(n-i)%mod+binom(i,m-i);
ans+=tmp;
ans%=mod;
}
for(int i=n;i<=m;++i){//PART 2
long long tmp=binom(n,i-n);
ans+=tmp;
ans%=mod;
}
if(m<n){//M<N
ans+=2*quickpow(2,n-m)+m-1;
ans%=mod;
}
printf("%lld",ans);
return 0;
}
:::