HDU 6134 Killer Names 数学 斯特林数

  题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6143

  题目描述: 有两个长度为N的串儿, 总共有m种字母, 要保证两个串没有一个相同的字母可选方案有多少种?

  解题思路: 啊啊啊啊啊啊啊啊, 受不了了.........太困了, 眼皮打架呢.........睡了睡了, 明天再写博客, 然后推公式, 然后看组合数学的八球公式, 然后整理板子, 然后收集样本......我们每次把i种字母分给A串, m-i种字母分给B串, 然后问题就转换成了, n个位置, 可以放i种球, 球不同, 箱子不同, 箱子不能为空这种问题, 正是二斯特林数.....套一下板子即可

  代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <stack>
#include <deque>
#include <map>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,-0x3f,sizeof(a))
#define fi(n) for(i=0;i<n;i++)
#define fj(m) for(j=0;j<m;j++)
#define sca(x) scanf("%d",&x)
#define ssca(x) scanf("%s",x)
#define scalld(x) scanf("%I64d",&x)
#define print(x) printf("%d\n", x)
#define printlld(x) printf("%I64d\n",x)
#define de printf("=======\n")
#define yes printf("YES\n")
#define no printf("NO\n")
typedef long long ll;
using namespace std;

const ll mod = 1e9+7;
const int maxn = 2100;
const int N = 5e3+6;

ll inv[N+10];
//ll c[maxn];
ll fac[N+10];
ll s[maxn][maxn];

int n;
int m;

ll qmod( ll num, ll t ) {
    ll res = 1ll;
    while( t ) {
        if( t & 1 ) res = res * num % mod;
        t >>= 1;
        num = num * num % mod;
    }
    return res;
}

void init() {
    fac[0] = 1;
    for( int i = 1; i <= N; i++ ) {
        fac[i] = fac[i-1] * i % mod;
    }
    inv[N] = qmod(fac[N], mod-2);//Fac[N]^{MOD-2}
    for (int i = N - 1; i >= 0; i--) inv[i] = inv[i+1] * (i + 1) % mod;
}

void init2() {
    mem0(s);
    s[1][1] = 1;
    for( int i = 2; i <= maxn-1; i++ ) {
        for( int j = 1; j <= i; j++ ) {
            s[i][j] = s[i-1][j-1]+j*s[i-1][j];
            if( s[i][j] >= mod ) s[i][j] %= mod;
        }
    }
}


ll C(int n, int m) {
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}

ll S(int n, int m) {
    return fac[m]*s[n][m]%mod;
}
int main() {
    init();
    init2();
    int t;
    sca(t);
    while( t-- ) {
        sca(n);
        sca(m);
        ll ans = 0;
        for( int i = 2; i <= m; i++ ) {
            for( int j = 1; j < i; j++ ) {
                ans += S(n, j)*S(n, i-j)%mod*C(m, i)%mod*C(i, j)%mod;
                ans %= mod;
            }
        }
        printf( "%lld\n", ans );
    }
    return 0;
}
View Code

  思考: 觉得自己对组合数还是理解得十分肤浅, 自己应该把八球问题都推一遍, 这样才不会太菜......还有今天同学来了啊, 一起出去玩, 当是放暑假了.......... 

  顺便安利一篇八球问题: https://bbs.qzzn.com/thread-14856448-1-1.html

posted on 2017-08-26 00:24  FriskyPuppy  阅读(137)  评论(0编辑  收藏  举报

导航