【NOIP模拟】小a的强迫症

Description

【NOIP模拟】小a的强迫症_第1张图片

Solution

由于组合数的基础不好,这题怎么想都想不出来。
但是有一个很显然的东西很容易看出来,最后一个颜色的柱子肯定要放在最后面。
那么现在只有n-1个位置了,最后一个颜色的柱子只剩下a[n]-1个了,但是这a[n]-1个可以随便乱放(很显然),那么贡献: Ca[n]1n1 ,然后考虑倒数第二个颜色,因为倒数第一个已经放完了,那么就会留下一些空,这些空的最后一个一定要把倒数第二个颜色放上去(很显然),那么倒数第二个也只剩下a[n-1]-1个了,格子数也只剩下n-a[n]-1个了,那么倒数第二个颜色的贡献就是 Ca[n1]1na[n]1 ,然后以此类推……
最后答案就是 1i=nCa[i]1nnj=i+1a[j]1 ,预处理一下,逆元用线性的求, O(n) 就搞定了。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=500007,mo=998244353;
ll i,j,k,l,t,n,m,ans,cas,shu;
ll a[maxn];
ll fact[maxn],ni[maxn];
ll qsm(ll x,ll y){
    ll z=1;
    while(y){
        if(y&1)z=z*x%mo;
        x=x*x%mo;
        y/=2;
    }
    return z;
}
ll c(ll x,ll y){
    return fact[x]*ni[y]%mo*ni[x-y]%mo;
}
int main(){
    scanf("%d",&n);
    fo(i,1,n)scanf("%d",&a[i]),shu+=a[i];
    fact[0]=ni[0]=1;
    fo(i,1,shu)fact[i]=fact[i-1]*i%mo;
    ni[shu]=qsm(fact[shu],mo-2);
    fod(i,shu-1,1)ni[i]=ni[i+1]*(i+1)%mo;
    ans=1;t=1;
    fod(i,n,1){
        ans=ans*c(shu-t,a[i]-1)%mo;
        t+=a[i];
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(noip,数论)