牛客IOI周赛18-提高组 C-山脉 题解

排列

https://ac.nowcoder.com/acm/contest/7225/A

考虑枚举山峰的最右边位置 ,那么 ~ 是一个不下降序列, ~ 也是个不下降序列。

考虑一个最大高度为 的不下降序列的方案数,做一下差分,那么有若干个位置不为 ,且这些位置的总和为 ,那么相当于将 分给这 个位置,由于数字都大于 ,所以第一个位置的差分值至少为 ,所以实际上是将 分给 个位置,方案数就是个插板法

答案就是:

后面那个部分是求杨辉三角一列的和,套公式得到:

改一下:

考虑化简里面的部分,其实里面就是在求:

这有点像一个卷积的形式,考虑生成函数,设

那么上面那个式子求出来的,其实就是 的第 项系数,即

所以 ,代入到上面的式子,得到:,这个就是答案了。

代码如下:

#include <cstdio>
#define maxn 15000010
#define mod 1000000007

int T,n,m;
int ksm(int x,int y){int re=1;for(;(y&1?re=1ll*re*x%mod:0),y;y>>=1,x=1ll*x*x%mod);return re;}
int fac[maxn],inv_fac[maxn];
void work(){
    fac[0]=inv_fac[0]=1;
    for(int i=1;i<=maxn-10;i++)fac[i]=1ll*fac[i-1]*i%mod;
    inv_fac[maxn-10]=ksm(fac[maxn-10],mod-2);
    for(int i=maxn-11;i>=1;i--)inv_fac[i]=1ll*inv_fac[i+1]*(i+1)%mod;
}
void add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
int C(int x,int y){
    if(x<y)return 0;
    return 1ll*fac[x]*inv_fac[y]%mod*inv_fac[x-y]%mod;
}

int main()
{
    work();
    scanf("%d",&T);while(T--)
    {
        scanf("%d %d",&m,&n);int ans=0;
        for(int i=1;i<=m;i++)add(ans,C(n+2*i-3,n-1));
        printf("%d\n",ans);
    }
}
全部评论

相关推荐

11-27 12:36
已编辑
门头沟学院 前端工程师
Apries:这个阶段来说,很厉害很厉害了,不过写的简历确实不是很行,优势删掉吧,其他的还行
点赞 评论 收藏
分享
11-02 09:49
已编辑
货拉拉_测试(实习员工)
热爱生活的仰泳鲈鱼求你们别卷了:没事楼主,有反转查看图片
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务