洛谷 1680 奇怪的分组

来源:互联网 发布:苏联生活水平数据 编辑:程序博客网 时间:2024/06/04 00:30

题目链接:奇怪的分组


题目大意:给你一个n和m,然后是m个c[i],要求你将n个数分在m个组里面,第i个组的人数必须大于c[i],问你一共有多少中情况


题目思路:实际上就是从n中分出去sigma(C[i])个数,然后剩下的数假定是sum,则就有sum-1个空,需要插m-1个板子进去,就是高中学的插板法,实际上就是算组合数C(sum-1,m-1,1e9+7),直接套Lucas板子就可以了

#include<bits/stdc++.h>typedef long long LL;using namespace std;const int p = 1e9+7;LL exp_mod(LL a, LL b, LL p) {    LL res = 1;    while(b != 0) {        if(b&1) res = (res * a) % p;        a = (a*a) % p;        b >>= 1;    }    return res;}LL Comb(LL a, LL b, LL p) {    if(a < b)   return 0;    if(a == b)  return 1;    if(b > a - b)   b = a - b;    LL ans = 1, ca = 1, cb = 1;    for(LL i = 0; i < b; ++i) {        ca = (ca * (a - i))%p;        cb = (cb * (b - i))%p;    }    ans = (ca*exp_mod(cb, p - 2, p)) % p;    return ans;}LL Lucas(int n, int m, int p) {     LL ans = 1;     while(n&&m&&ans) {        ans = (ans*Comb(n%p, m%p, p)) % p;        n /= p;        m /= p;     }     return ans;}int main() {    int n,m,x;    while(~scanf("%d%d",&n,&m)){        LL sum = 0;        for(int i = 0;i < m;i++){            scanf("%d",&x);            n -= x;        }        printf("%lld\n", Lucas(n-1,m-1,p));    }    return 0;}


0 0