牛客小白月赛17 J计数 单调不增序列方案数

链接:https://ac.nowcoder.com/acm/contest/1085/J
来源:牛客网

题目描述

小sun最近对计数问题来了兴趣,现在他有一个问题想问问你:

有一个含有n个数字的序列,每个数的大小是不超过1000的正整数,同时这个序列是个单调不增序列。但是很不幸的是,序列在保存过程中有些数字丢失了,请你根据上述条件,计算出有多少种不同的序列满足上述条件,答案对1000000007取模。(具体可以看样例)

输入描述:

第一行包含一个整数n,表示这个序列的长度。

第二行为n个整数ai,用空格隔开,如果数字是0,代表这个数字丢失了,其他的数字都在1~1000之间

输出描述:

输出一行,表示答案。

示例1

输入

3
9 0 8

输出

2

示例2

输入

2
5 4

输出

1

示例3

输入

3
0 0 0

输出

167167000

备注:

1≤n≤1e6
0≤ai≤10000

题解:

牛客小白月赛17 J计数 单调不增序列方案数_第1张图片

上图是牛客官方题解, 和我想的一样,我dp打出表之后看出这个组合数公式 , 然后发现这个公式和盒子放球模型里的一个公式一样,然后发现这两个问题等价。

一个长度为n的序列,每个数字在1到m 之间,序列单调不增的方案数。

上述这个问题和盒子放球问题中的这个问题类似:把n个不同的球全部放到m个不同的盒子里,盒子允许为空的方案数。

这个问题高中就学过,隔板法,插空法。

设1到m这m个数字取的个数分别为a1,a2....am. 那么  a1+a2+....am=n. 并且 ai>=0

每种取法都对应一种序列。

代码:

#include
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
const int mod=1e9+7;
int a[maxn];
ll fac[maxn],ni[maxn];
ll ksm(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
ll C(ll n,ll m){
    if(n=0;i--){
        ni[i]=ni[i+1]*(i+1)%mod;
    }
}
int main(){
    init();
    int n;
    scanf("%d",&n);
    for(int i=0;ip){
                ans=0;
                break;
            }
            int m=p-a[i]+1;
            ans=ans*C(cnt+m-1,m-1)%mod;
            p=a[i];
            cnt=0;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

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