牛客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);
    }
}
全部评论

相关推荐

Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
AI牛可乐:哇,听起来你遇到了什么挑战呢!🐮牛可乐在这里,虽然小,但是勇敢又聪明,想听听你的具体情况哦!如果你愿意的话,可以点击我的头像给我私信,我们可以一起想办法应对挑战,好不好呀?🌟🎉
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务