数组(组合数学)

数组(数学)

【问题描述】

fabdec 有⼀个长度为 n 的数组 \(a[]\)(下标 1-n), 初始时都是 0。 fabdec 随机了⼀个 1 到 n 的随机数 x,并且把 \(a[x]++\)
fabdec 重复了 m 次这样的操作,然后数了⼀下数组⾥⼀共有 k 个位置 为奇数。 fabdec 现在想问执⾏ m 次操作,总共能⽣成多少种不同的数组使得恰 好有 k 个位置是奇数?
(两个数组不同当且仅当两个数组存在某个位置数组 的值不相同)
因为这个数字会很⼤,所以只需输出这个答案除以 109 + 7 的余数。

【输入格式】

⼀⾏三个整数,n,m,k。

【输出格式】

输出包含⼀个整数,表⽰答案。

【样例输入】

2 3 1

【样例输出】

4

【数据规模及约定】

对于前 20% 的数据,1 ≤ n,m ≤ 4。
对于前 50% 的数据,1 ≤ n,m ≤ 2000。
对于前 100% 的数据,1 ≤ n,m ≤ 105, 0 ≤ k ≤ n。

看到这个题,我们化简题意可得:
m分成n个数,要求这n个数中正好有k个奇数,问合法的排列有多少个。(也可以说成n个数的和为m)
---

我们考虑组合数的做法:
因为要求是k个奇数,所以我们要从n个数里面选取k个数当作奇数,这一步是\(C_n^k\)的。
我们设这n个数分别为\(a_1,a_2,...,a_n\),那么我们知道\[\sum_{i=1}^na_i=m\]
但是数字中有奇数有偶数不方便处理,所以我们考虑把所有数字都换成偶数,那么在等式的左右两边同时减去k,我们就可以认为是\(m-k\)分成了n个偶数。
又由于偶数除以2可能为奇数,可能为偶数,所以当我们在等式的左右两边同时除2的时候,该问题就转化成了将\(\frac{m-k}{2}\)分成\(n\)份(其中可以每一份的个数可以为0),有多少种不同的分法(顺序不同也视作不同)的问题了。运用到我们高中数学中的隔板法,我们可以知道这一步的答案是\(C_{\frac{m-k}{2}+n-1}^{n-1}\),所以运用乘法原理,我们可以知道答案是\[C_{n}^k\times C_{\frac{m-k}{2}+n-1}^{n-1}\]
之后就很简单了,但是由于题目是在模意义下,所以要求逆元。逆元用费马小定理+快速幂很容易就能求出来。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
// by zrt
using namespace std;

typedef long long LL;

LL n,m,k;
const LL mod=1e9+7;
LL pow(LL a,LL b,LL p){
    LL ret=1%p;
    while(b){
        if(b&1) ret=ret*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ret;
}
LL fac(LL n){
    LL ret = 1%mod;
    for(int i=1;i<=n;i++) ret=ret*i%mod;
    return ret;
}
LL invfac(LL n){
    return pow(fac(n),mod-2,mod);
}
LL C(LL n,LL m){
    if(n<m)return 0;
    return fac(n)*invfac(m)%mod*invfac(n-m)%mod;
}
int main(){
    freopen("array.in","r",stdin);
    freopen("array.out","w",stdout);
    cin>>n>>m>>k;
    if(k>=m) cout<<0<<endl;
    else if((m-k)&1) cout<<0<<endl;
    else cout<< C(n,k)*C((m-k)/2+n-1,n-1)%mod<<endl;
    return 0;
}

转载于:https://www.cnblogs.com/fengxunling/p/9738721.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值