山东省第五届ACM大学生程序设计竞赛-Hearthstone II(组合数学-第二类Stirling数)

Hearthstone II

Time Limit: 2000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

The new season has begun, you have n competitions and m well prepared decks during the new season. Each competition you could use any deck you want, but each of the decks must be used at least once. Now you wonder how many ways are there to plan the season — to decide for each competition which deck you are going to used. The number can be very huge, mod it with 10^9 + 7.
 

输入

The input file contains several test cases, one line for each case contains two integer numbers n and m (1 ≤ m ≤ n ≤ 100).
 

输出

One line for each case, output one number — the number of ways.

示例输入

3 2
100 25

示例输出

6
354076161

提示

 

来源

2014年山东省第五届ACM大学生程序设计竞赛

题目意思:

输入两个数n,m,n是总数,n个中有m个是备选的。
要在m中至少选一个,求总数n中共有多少种组合的情况。

例如题目中的3 2:
即n=3,有A B C三个数;m=2,A B备选但必须至少选一个;
所有所有可能的选法是:
A
B
A B
A C
B C
A B C
就是说选法中必须要有 A B 中的至少一个。

解题思路:

(传送门→)组合数学-第二类Stirling数。
但是本题中m可区分,对于第二类Stirling数中求得的是m不可区分的情况下所有的组合总数。
所以需要用for循环遍历,把1~m这m种情况下的S全部相加起来才是本题的结果。



/*
* Copyright (c) 2016, 烟台大学计算机与控制工程学院
* All rights reserved.
* 文件名称:Stirling.cpp
* 作    者:单昕昕
* 完成日期:2016年4月22日
* 版 本 号:v1.0
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
long long s[101][101];
const long long mod=1000000007;
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {//初始化
        memset(s,0,sizeof(s));
        s[n][1]=1;
        s[n][n]=1;
        s[1][1]=1;
        int i,j;
        for(i=2; i<=100; i++)//先根据数据范围把所有s求出来
            for(j=1; j<=i; j++)
                s[i][j]=(s[i-1][j-1]+j*s[i-1][j])%mod;
        long long ans=s[n][k];
        for(i=2; i<=k; i++)//根据题意,k可区分
        {
            ans*=i;
            if(ans>=mod)
                ans%=mod;
        }
        printf("%lld\n",ans);
        //cout<<ans<<endl;
    }
    return 0;
}


你可能感兴趣的:(C++,ACM,组合数学,II,第二类Stirling数,Hearthstone)