[ABC405E] Fruit Lineup 题解
思路
可以发现苹果一定在香蕉的前面,所以我们可以将橘子和葡萄插入苹果和香蕉中。
设 dpidp_idpi 表示将橘子只放在前 iii 个空(共有 a+c+1a+c+1a+c+1 个空)时的方案数。
此时橘子的方案数为将 b−1b-1b−1 个橘子放到 iii 个空的方案数(有一个橘子强制放在最后一个,iii 从 0 开始),即为 (b+i−1b−1)\binom{b+i-1}{b-1}(b−1b+i−1)。
葡萄方案数为将 ddd 个葡萄插到 min(c,a+c−i)\min(c,a+c-i)min(c,a+c−i) 个空里的方案数(ccc 是为了方止葡萄插到苹果的前面,a+c−ia+c-ia+c−i 是为了防止葡萄插到橙子前面),即为 (min(c,a+c−i)+dd)\binom{\min(c,a+c-i)+d}{d}(dmin(c,a+c−i)+d)。
所以 dpidp_idpi 的状态转移方程为:
dpi=(b+i−1b−1)(min(c,a+c−i)+dd)dp_i=\binom{b+i-1}{b-1}\binom{\min(c,a+c-i)+d}{d}dpi=(b−1b+i−1)(dmin(c,a+c−i)+d)
最终答案为:
∑i=1n(b+i−1b−1)(min(c,a+c−i)+dd)\sum_{i = 1}^{n}\binom{b+i-1}{b-1}\binom{\min(c,a+c-i)+d}{d}∑i=1n(b−1b+i−1)(dmin(c,a+c−i)+d)
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
ll a,b,c,d,dp[4000010],f[4000010];
ll qpow(ll a,ll b){//快速幂
ll ans=1%mod;
for(;b;b>>=1,a=(a*a)%mod)if(b&1)ans=(ans*a)%mod;
return ans;
}
ll calc(ll a,ll b){//将a个数插到b个水果周围的空(即为b-1个空)的方案数
return f[a+b]*qpow(f[a],mod-2)%mod*qpow(f[b],mod-2)%mod;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>a>>b>>c>>d;
f[0]=1;
f[1]=1;
for(int i=2;i<=4e6;i++){//阶乘
f[i]=f[i-1]*i%mod;
}
ll ans=0;
for(int i=0;i<=a+c;i++){//dp
dp[i]=max(calc(b-1,i),1ll)*max(calc(d,min(c,a+c-i)),1ll)%mod;
ans=(ans+dp[i])%mod;
}
cout<<ans;
return 0;
}

989

被折叠的 条评论
为什么被折叠?



