• 【搜索】【组合数学】zoj3841 Card


    转载自:http://blog.csdn.net/u013611908/article/details/44545955

    题目大意:一副牌除掉大小王,然后有一些已经形成了序列,让你算剩下的牌能组合出多少种比给的序列小的组合。

    思路:搜索,分这个位置相同或者小于,假如放一个小于的,则剩下的就是全排列

    只不过这边的全排列是相同元素的全排列。

    所采取的是位置的选择的排列方式。

    比如1112233这个所有的情况就是c(7,3)*c(4,2)*c(2,2)

    题目wa了很多发。

    题目需要注意,是严格小于,等于是不行的。

    另外就是涉及到剩的张数比给的少的情况。

    这边直接给数据让大家测试吧,ps:是抄别人的。

    Input:
    KKKKQQQQJJJJ10101010999988887777666655554444
    K
    AA22334455667788991010JJKKK
    KAA22334455667788991010JJQK
    KKKKJJJJQQQQ1010101099998888777766665555444433332222AAAA
    AA22334455667788991010JJKKQQ
    KKKJJJJQQQQ1010101099998888777766665555444433332222AAAA

    Output:
    34650
    944696453
    5
    596617684
    0
    5
    1
     
    #define _CRT_SECURE_NO_WARNINGS  
    #include<iostream>  
    #include<cstring>  
    #include<cstdio>  
    using namespace std;  
    #define mod 1000000007  
    int a[15];  
    char str[60];  
    long long ans = 0;  
    long long c[60][60];  
    void init()  
    {  
        for (int i = 0; i < 60;i++)c[i][0] = c[i][i] = 1;  
        for (int i = 2; i < 60;i++)  
        for (int j = 1; j < i; j++)  
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1])%mod;  
    }  
    long long gao(int sum)  
    {  
        long long ans = 1;  
        for (int i = 1; i < 14; i++)  
        {  
            ans = (ans*c[sum][a[i]])%mod;  
            sum -= a[i];  
        }  
        return ans;  
    }  
    void dfs(int cur, int sum)  
    {  
        if (!str[cur])  
        {  
            return;  
        }  
        if (sum == 0)  
        {  
            ans++;  
            return;  
        }  
        int k = str[cur] - 48;  
        for (int i = 1; i<k; i++)  
        {  
            if (a[i]>0)  
            {  
                a[i]--;  
                ans = (ans + (gao(sum-1)) % mod) % mod;  
                a[i]++;  
            }  
        }  
        if (a[k]>0)  
        {  
            a[k]--;  
            dfs(cur + 1, sum - 1);  
        }  
    }  
    int main()  
    {  
        init();  
        while (~scanf("%s", str))  
        {  
            int len = strlen(str);  
            int j = 0;  
            for (int i = 1; i < 14; i++)  
                a[i] = 4;  
            for (int i = 0; i < len; i++)  
            {  
                if (str[i] == 'A')  
                {  
                    str[j++] = 1 + 48;  
                    a[1]--;  
                }  
                else  
                if (str[i] == '1')  
                {  
                    str[j++] = 10 + 48;  
                    a[10]--;  
                }  
                else  
                if (str[i] == 'J')  
                {  
                    str[j++] = 11 + 48;  
                    a[11]--;  
                }  
                else  
                if (str[i] == 'Q')  
                {  
                    str[j++] = 12 + 48;  
                    a[12]--;  
                }  
                else  
                if (str[i] == 'K')  
                {  
                    str[j++] = 13 + 48;  
                    a[13]--;  
                }  
                else  
                if (str[i] == '0')  
                    continue;  
                else  
                {  
                    str[j++] = str[i];  
                    a[str[i] - 48]--;  
                }  
            }  
            str[j] = 0;  
            int sum = 0;  
            for (int i = 1; i < 14; i++)  
                sum += a[i];  
            ans = 0;  
            if (sum != 0)  
            dfs(0, sum);  
            printf("%lld
    ", ans);  
        }  
        return 0;  
    }  
  • 相关阅读:
    一次安装。net core的经历
    c# task 等待所有子线程执行完的写法
    .net 中的async,await理解
    dbeaver pgsql连接工具
    oracle 导出表结构和备注
    abp
    发布站点
    excel 拆分多个excel并保持
    重定向和反向代理的区别
    es6中的解构赋值
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/8358021.html
Copyright © 2020-2023  润新知