hdu-4045-Machine scheduling-组合数学(插板+第二类Stirling数)

http://acm.hdu.edu.cn/showproblem.php?pid=4045


题意: n个机器,每天选择r个机器,这任意r个机器编号差>=k,并且将它们分成不到m个相同的组,一共多少方案?


一是 把n机器每天选r个 编号差》k的方案

二是把r个机器分成小于等于m个组的方案
二者乘积就是答案


对于1: 既然要编号差大于等于k,先令每个机器间编号差为k,那么剩下 res=n-k*(n-1)-1个机器没用
接下来把res个机器插到 空隙中,根据插板法,在r个机器的r+1个空隙中插res个机器的方案为 :C(r+res,r)


第二种情况就是Stirling(r,m)


注意取模:


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>

#include <iostream>


using namespace std;
const long long mod=1000000007;
int ss[1005][1005];
int  cc[2005][2005];  //内存限制为 C(n,k)中的n*k
void pre()
{
    int i,j;
    for (i=0; i<=2000; i++)
    {
        cc[i][0]=1;  //c(i,0)=1;
    }
    for (i=1; i<=2000; i++)
    {
        for (j=1; j<=2000; j++)
            cc[i][j]=(cc[i-1][j-1]+cc[i-1][j])%mod;
    }
}
void spre()
{
     for (int i=1; i<=1000; i++)
        ss[i][0]=0;
    for (int i=0; i<=1000; i++)
        ss[i][i]=1;
    for (int i=1; i<=1000; i++)
    {
        for (int j=1; j<=i-1; j++)
        {
            ss[i][j]=(j*(long long )ss[i-1][j]%mod+ss[i-1][j-1])%mod;
        }
    }
}

int  main()
{
    pre();
     spre();

    int n,k,r,m;
    while(scanf("%d%d%d%d",&n,&r,&k,&m)!=EOF)
    {
        long long res=n-(r-1)*k-1;
        if (res<0)
        {
            printf("0\n");continue;
        }
        long long ans=0;
        for (int i=0; i<=m; i++)
            ans=(ans+ss[r][i])%mod;
        ans*=cc[res+r][r];

        printf("%lld\n",ans%mod);
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值