斯特林数stirling
- 第一类 stirling数 s(n, k)
n个人分成k组,组内再按特定顺序围圈
也就是分成了k组,组内就像是项链颜色一样,
- ( {A, B}, {C, D} )
- ( {B, A}, {C, D} )
属于一组
- ({A}, {B, C, D})
- ({A}, {B, D, C})
不属于一组
给定 $s(n,0)=0,s(1,1)=1$,有递归关系$s(n,k)=s(n-1,k-1) + (n-1) s(n-1,k)$
- 第二类 stirling数
S(n, k) 是把p元素集合划分到k个不可区分的盒子里且没有空盒的划分个数。
公式:
$$ S(n, n) = 1 (n >= 0) $$
$$ S(n, 0) = 0 (n >= 1) $$
$$ S(n,k)=k*S(n-1,k)+S(n-1,k-1),\text (1<=k<=n-1) $$
这样题目就好解决了。第五届省赛题目神经病。
因为每个桌子是不同的,所以还要利用乘法原理,$ans*m!$
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <map> #include <algorithm> #include <queue> #include <cmath> #include <bitset> using namespace std; // 大数,内存处理 #define INF 0x3f3f3f3f #define lln long long int #define MEM(a) memset(a, 0, sizeof(a)) #define MEMM(a) memset(b, -1, sizeof(b)) #define DEB(x, n) cout << (x) << " " << (n) << endl const double PI = acos(-1.0); #define CR printf("\n") // 调试用 template <class Type> void debug(Type a[], int len) { for(int i = ; i < len ; i++) { cout << a[i] << " "; } cout << endl; } #define mod 1000000007 const int maxn = 100 + 10; lln s[maxn][maxn]; void init() { for(int i = ; i < 101; i++) { s[i][] = ; s[i][i] = 1; } for(int n = 2; n < 101; n++) for(int k = 1; k <= n-1 ; k++) s[n][k] = ((k*s[n-1][k])%mod + s[n-1][k-1]%mod) %mod; } int readinput() { int m, n; if(scanf("%d%d", &n, &m) == EOF) return ; else { lln ans = s[n][m]; for(int i = 2; i <= m; i++) { ans *= i; ans %= mod; } printf("%lld\n", ans); } return 1; } int main() { #ifdef DEBUG // freopen("input", "r", stdin); //从input文件中读入 // freopen("output", "w", stdout); //输出到output文件 #endif init(); while(readinput()); return ; }