7.10模拟赛

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;
}

猜你喜欢

转载自www.cnblogs.com/ghostcai/p/9289735.html