T1.qiang
不写逆元见祖宗..
首先一个合法方案最少要包含一个形如1,2,3,..n的数列,再考虑在其中插入一些数。
考虑以x结尾的一种方案,x贡献了了num[x]次,在初始序列中出现了一次,所以贡献了num[x]-1次,其中的每一种,都有sum[x]-1个地方可以放(至少放在x前,不然就违背了定义)
所以答案就是π(C(sum[i]-1,num[i]-1))(之前都想得很正常,接下来开始表演爆0)
具体计算组合数时,显然要预处理阶乘,然而这里有乘法,所以要用逆元(这不是显然吗,我的脑子呢..)
#include<iostream> #include<cstdio> using namespace std; const int MAXN=500005; const int N=500000; const int MOD=998244353; typedef long long ll; inline ll rd(){ ll ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } ll po(ll x,ll y) { ll ret=1,base=x; while(y) { if(y&1) (ret*=base)%=MOD; (base*=base)%=MOD; y>>=1; } return ret; } ll fac[MAXN],inv[MAXN]; void prework() { fac[0]=1; for(int i=1; i<=N; i++) fac[i]=(fac[i-1]*i)%MOD; inv[N]=po(fac[N],MOD-2); for(int i=N-1; i>=0; i--) inv[i]=(inv[i+1]*(i+1))%MOD; } inline ll C(ll x,ll y){ if(y>x) return 0; return (1ll*(fac[x]*inv[y])%MOD*inv[x-y])%MOD; } ll ans=1; ll n; ll num[MAXN],sum[MAXN]; int main() { prework(); n=rd(); for(int i=1;i<=n;i++) num[i]=rd(),sum[i]=sum[i-1]+num[i]; for(int i=1;i<=n;i++){ ans*=C(sum[i]-1,num[i]-1); ans%=MOD; } cout<<ans<<endl; return 0; }