zoj 3841 Cards

zoj 3841 Cards

题目链接:
点击打开链接

题意:
给出一副扑克牌
先定义扑克牌的优先级
A < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K
给出 一个已知的扑克牌排列
问 剩下的扑克牌 能排出多少种比 给出的扑克牌序列 字典序小的方案。

思路:
dfs+组合数学
从前到后搜
每到一位,根据前面相等和不相等的情况分别处理
如果相等,继续往下搜
如果不相等,直接用组合数计算答案,如:
1 1 1 2 2 3 3
种数 = C(7,3)*C(4,2)*C(2,2)

附上几组测试数据:
Input:
KKKKQQQQJJJJ10101010999988887777666655554444
K
AA22334455667788991010JJKKK
KAA22334455667788991010JJQK
KKKKJJJJQQQQ1010101099998888777766665555444433332222AAAA
AA22334455667788991010JJKKQQ
KKKJJJJQQQQ1010101099998888777766665555444433332222AAAA

Output:
34650
944696453
5
596617684
0
5
1

/*zoj3841
  题意:
  给出一副扑克牌
  先定义扑克牌的优先级
  A < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K
  给出 一个已知的扑克牌排列
  问 剩下的扑克牌 能排出多少种比 给出的扑克牌序列 字典序小的方案。
  思路:
  dfs+组合数学
  从前到后搜
  每到一位,根据前面相等和不相等的情况分别处理
  如果相等,继续往下搜
  如果不相等,直接用组合数计算答案,如:
  1 1 1 2 2 3 3
  种数 = C(7,3)*C(4,2)*C(2,2)
 */
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
        
        
using namespace std;
const int MOD=1000000007;
#define LL long long
char str[105];
int a[105];
int tab[20];
int len;
LL Ext_gcd(LL a,LL b,LL &x,LL &y){
    if(b==0) { x=1, y=0; return a; }
    LL ret= Ext_gcd(b,a%b,y,x);
    y-= a/b*x;
    return ret;
}

LL Inv(LL a,int m){
    LL d,x,y,t= (LL)m;
    d= Ext_gcd(a,t,x,y);
    if(d==1) return (x%t+t)%t;
    return -1;
}

LL Cm(LL n, LL m, LL p){
    LL a=1, b=1;
    if(m>n) return 0;
    while(m){
        a=(a*n)%p;
        b=(b*m)%p;
        m--;
        n--;
    }
    return (LL)a*Inv(b,p)%p;
}
int tran(char c){
    if(c=='A') return 0;
    else if(c=='0') return 9;
    else if(c>='2' && c<='9') return c-'1';
    else if(c=='J') return 10;
    else if(c=='Q') return 11;
    else if(c=='K') return 12;
}
LL gao(int p,int eq,int _sum,int tab[]){    //p表示第几位,eq前面表示是否相等,0表示不等,1表示相等,
                                            //_sum表示剩下多少张扑克牌,tab[]表示每种扑克牌剩下几张
    LL ret=0;
    if(p==len){
        if(eq==1) return 0;
    }
    if(_sum==0 && p){
        return 1;
    }
    if(eq==0){
        ret=1;
        for(int i=0;i<=12;++i){
            ret=(ret*Cm(_sum,tab[i],MOD))%MOD;
            _sum-=tab[i];
        }
        return ret;
    }
    else{
        for(int i=0;i
        
        
       
       
      
      
     
     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值