题解 | #Bheith i ngra le#

Bheith i ngra le

https://ac.nowcoder.com/acm/contest/17574/B

来一发B题的组合数学的解法
首先考虑比较朴素的做法,枚举区间l,r枚举这个区间的值,然后用隔板法计数,复杂度O(n^3)
我们用公式表示(来自官方题解
图片说明
我们发现第一个式子和j没关系,第二个式子和i没关系
操作一个这个公式变成
图片说明
那么我们只需要预处理出图片说明 计为num[i][k]
那么最后答案的计算可以变成
图片说明
这里如何处理num数组的时候可以使用前缀和的方式,

num[i][k] = pre[n][k] - pre[i-1][k]

Code:

ll fun[maxn],inv[maxn];
ll C(ll n,ll m) {
    if(n<m) return 0;
    if(m==0) return 1;
    if(n==m) return 1;
    return (fun[n]*inv[n-m]%mod)*inv[m]%mod;
}
ll qpow(ll a,ll b) {
    ll ans=1;
    while(b) {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
void yu() {
    inv[1]=1,fun[1]=1,fun[0]=1;
    for(int i=2; i<maxn; i++) fun[i]=fun[i-1]*i%mod;
    inv[maxn-1]=qpow(fun[maxn-1],mod-2);
    for(int i=maxn-2; i>=0; i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll n,m,pre[2020][2020],num[2020][2020];
int main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    yu();
    for(int k=1 ;k<=m; k++)
    {
        for(int j=1 ;j<=n ;j++)
        {
            pre[j][k] = pre[j-1][k] + C(n-j+k-1,k-1);
            pre[j][k]%=mod;
        }
    }
    for(int k=1 ;k<=m ; k++)
    {
        for(int i=1 ;i<=n ;i++)
        {
            num[i][k] = pre[n][k] - pre[i-1][k];
            num[i][k]%=mod;
        }
    }
    ll ans=0;
    for(int i=1 ;i<=n ;i++)
    {
        for(int k=1 ;k<=m ;k++)
        {
            ans = (ans+C(i+k-2,k-1)*num[i][k])%mod;
        }
    }
    cout<<(ans+1)%mod<<endl;
    return 0;
}
全部评论
官方题解的第一个式子是怎么推出来的?
2 回复 分享
发布于 2021-06-15 21:15
逮到辣
1 回复 分享
发布于 2021-06-18 15:17
666
点赞 回复 分享
发布于 2021-06-15 13:37

相关推荐

12-19 21:56
已编辑
中山大学 Java
灵犀互娱 中台组 1085
点赞 评论 收藏
分享
伟大的烤冷面被普调:暨大✌🏻就是强
点赞 评论 收藏
分享
评论
4
收藏
分享
牛客网
牛客企业服务