【NOIP2016提高A组模拟9.17】小a的强迫症

题目

这里写图片描述

分析

题目要求第i种颜色的最后一个珠子要在第i+1种颜色的最后一个珠子之前,
那么我们从小到大枚举做到第i种,把第i种的最后一颗珠子取出,将剩下的\(num(i)-1\)个珠子插入已排好的前i-1种中,再将取出的珠子放在最后一个。
每次求出将剩下的\(num(i)-1\)个珠子插入已排好的前i-1种中的方案数,将它乘以ans。
对于每个i的方案数可以用隔板问题来求。
但是,在比赛上,我忘了隔板问题,于是再枚举个j,将已经排好的珠子分成j份,将要放进去的的\(num(i)-1\)个珠子找出j个空位(包括头和尾),将这j份珠子放入j个空位。
结果搞了半天,唉,说多了都是泪啊。。。

注意预处理阶乘,除法用逆元。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=998244353;
const long long N=100005;
using namespace std;
long long jc[N*10],a[N],sum[N],n,m,ans,ny[N*10];
long long c(long long m1,long long n1)
{
    return jc[m1]*ny[n1]%mo*ny[m1-n1]%mo;
}
long long mi(long long x,long long y)
{
    long long sum=1;
    while(y)
    {
        if(y&1) sum=sum*x%mo; 
        x=x*x%mo;
        y/=2;
    }
    return sum;
}
int main()
{
    jc[0]=1;
    for(long long i=1;i<=N*5-1;i++) jc[i]=jc[i-1]*i%mo;
    for(long long i=0;i<=N*5-1;i++) ny[i]=mi(jc[i],mo-2);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=a[i]+sum[i-1];
    }
    ans=1;
    for(int i=2;i<=n;i++)
    {
        long long k=0;
        for(long long j=1;j<=a[i] && j<=sum[i-1];j++)
        {
            k=(k+c(a[i],j)*((j==1)?1:c(sum[i-1]-1,j-1))%mo)%mo;
        }
        ans=(ans*k)%mo;
    }
    cout<<ans;
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9051648.html
今日推荐