• HDU


    题意:从m种字母中选取字母组成姓名,要求姓和名中不能有相同的字母,姓和名的长度都为n,问能组成几种不同的姓名。

    分析:

    1、从m种字母中选取i种组成姓,剩下m-i种组成名。

    2、i种字母组成长度为n的姓-----可转换成用i种颜色给n个球染色,记忆化搜索

    dfs(n,i)---用i种颜色给n个球染色的方案数

    先给第1个小球涂色,有m种选择,假设涂色为color[1],

    那么剩下n-1个小球:

    如果继续使用color[1],则问题转化为用m种颜色给n-1个小球涂色;

    如果不再使用color[1],则问题转化为用m-1种颜色给n-1个小球涂色;

    因此,dfs(n,i) = m * (dfs(n - 1, m - 1) + dfs(n - 1, m))。

    3、m-i种字母组成长度为n的名,名字中每个字母有m-i种选择,因此方案数为(m - i)n

    4、由此可列式:C[m][i] * dfs(n, i) * POW_MOD(m - i, n)   (1<=i<=min(n,m))

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cmath>
    #include<iostream>
    #include<sstream>
    #include<iterator>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<deque>
    #include<queue>
    #include<list>
    #define lowbit(x) (x & (-x))
    const double eps = 1e-8;
    inline int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a > b ? 1 : -1;
    }
    typedef long long LL;
    typedef unsigned long long ULL;
    const int INT_INF = 0x3f3f3f3f;
    const int INT_M_INF = 0x7f7f7f7f;
    const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
    const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
    const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
    const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
    const LL MOD = 1e9 + 7;
    const double pi = acos(-1.0);
    const int MAXN = 2000 + 10;
    const int MAXT = 10000 + 10;
    using namespace std;
    LL C[MAXN][MAXN];//组合数
    LL A[MAXN];//阶乘
    LL dp[MAXN][MAXN];
    void init(){
        A[1] = 1;
        for(int i = 0; i < MAXN; ++i){
            C[i][0] = C[i][i] = 1;
            if(i > 1) A[i] = A[i - 1] * i % MOD;
            for(int j = 1; j < i; ++j){
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
            }
        }
    }
    LL dfs(LL n, LL m){
        if(dp[n][m]) return dp[n][m];
        if(n == m) return dp[n][m] = A[n];
        if(m == 1) return dp[n][m] = 1;
        return dp[n][m] = m * ((dfs(n - 1, m - 1) + dfs(n - 1, m)) % MOD) % MOD;
    }
    LL POW_MOD(LL n, LL m){
        if(m == 0) return 1;
        LL tmp = POW_MOD(n, m / 2);
        LL ans = tmp * tmp % MOD;
        if(m & 1) (ans *= n) %= MOD;
        return ans;
    }
    int main(){
        int T;
        scanf("%d", &T);
        init();
        while(T--){
            LL n, m;
            scanf("%lld%lld", &n, &m);
            LL ans = 0;
            for(LL i = 1; i <= min(n, m); ++i){
                (ans += ((C[m][i] * dfs(n, i)) % MOD) * POW_MOD(m - i, n) % MOD) %= MOD;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    如何drop有default constraint的column SQL
    Asp.net中文本框全选的实现
    [转载]找回被误删的VISTA“显示桌面”图标
    [转]深入讲解数据库中User和Schema的关系
    模拟键盘输入
    ASP.NET页面之间传递值的几种方法
    查询整个数据库中某个特定值所在的表和字段的方法
    .NET的GCHandler
    DateTime.ToString() Patterns
    VS 2008的Setup project项目添加卸载功能
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/7384072.html
Copyright © 2020-2023  润新知