P4609 [FJOI2016]建筑师

传送门

转化为一个模型就是把(n)个不同的物品放进(m)个相同的盒子里,然后盒子里的物品进行圆排列,那么就是第一类斯特林数了

假设从度为n的柱子已经确定了
那么划分为两块了
左边看,还需要选择A-1块建筑块,右边看,还需要选择(B-1)块建筑物
在一个建筑块里面,如果一个标志物品(最高的那个)选择了,那么在左边就要放在最左边块,右边的话就要放在最右边块.
那么对于大小为(k)的建筑块来说,有((k-1)!)种方案相当于是这一块进行圆排列
类似于这种,每个建筑块里面都有一个标志物品,然后其他的物品进行全排列.相当于是这个建筑块进行园排列

(n-1)个物品划分为(A+B-2)个建筑块然后每一块进行园排列.最后在这(A+B-2)个建筑块里面选择(A-1)个块放在左边

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
using namespace std;
template<typename T = long long> inline T read() {
    T s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
    return s * f;
}
#ifdef ONLINE_JUDGE
#define qaq(...) ;
#define qwq(c) ;
#else
#define qwq(a, b) for_each(a, b, [=](int x){cerr << x << " ";}), cerr << std::endl
template <typename... T> void qaq(const T &...args) {
    auto &os = std::cerr;
    (void)(int[]){(os << args << " ", 0)...};
    os << std::endl;
}
#endif
const int N = 2e5 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
int C[305][305], S[50005][305];
void solve(int kase){
    S[0][0] = C[0][0] = 1;
    for (int i = 0; i <= 300; i++) C[i][i] = C[i][0] = 1;
    for(int i = 1; i <= 300; i++) {
    	for(int j = 0; j <= i; j++) {
    		if(j == 0 || i == j) C[i][j] = 1;
    		else C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
    	}
    }
    for(int i = 1; i <= 50000; i++) {
    	for(int j = 1; j <= min(i, 300); j++) {
    		S[i][j] = (S[i - 1][j - 1] + 1ll * S[i - 1][j] * (i - 1) % MOD) % MOD;
    	}
    }
    int t = read();
    for(int i = 1; i <= t; i++) {
    	int n = read(), a = read(), b = read();
    	printf("%lld
", 1ll * S[n - 1][a + b - 2] * C[a + b - 2][a - 1] % MOD);
    }
}
const bool ISFILE = 0, DUO = 0;
int main(){
    clock_t start, finish; start = clock();
    if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
    if(DUO) {CASE solve(kase);} else solve(1);
    finish = clock(); 
    qaq("
Time:", (double)(finish - start) / CLOCKS_PER_SEC * 1000, "ms
");
    return 0;
}
I‘m Stein, welcome to my blog
原文地址:https://www.cnblogs.com/Emcikem/p/14632995.html