歌名 - 歌手
0:00

    【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;
    }
    
    
    posted @ 2018-05-17 16:10  无尽的蓝黄  阅读(111)  评论(0编辑  收藏  举报