zoj 3841 Cards

题意:给你52张牌,已知一个牌的序列,然后利用剩余的牌,能排成多少个序列,这个序列比已知的序列字典序小。

思路:从左到右尽可能放比已知序列相应位置小,找不到就放一样,然后求组合数就可以。多重集排列定理:令s时一个多重集,有k个不同类型的元素,各元素的重数分别为n1,n2......nk,令s的大小为n=n1+n2+......nk,则s的排列数为    n!/(n1!*n2!.....nk!);

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <algorithm>

  4 #include <map>

  5 #define ll long long

  6 #define maxn 100010

  7 using namespace std;

  8 const int mod=1000000007;

  9 

 10 char str[maxn];

 11 int num[maxn];

 12 ll f[maxn];

 13 map<char,int>q;

 14 

 15 void inti()

 16 {

 17      f[0]=1;

 18      for(int i=1; i<=50; i++)

 19         f[i]=(f[i-1]*i)%mod;

 20      q['A']=1;

 21      for(int i=2; i<=9; i++)

 22         q['0'+i]=i;

 23      q['1']=10;

 24      q['J']=11;

 25      q['Q']=12;

 26      q['K']=13;

 27 }

 28 

 29 ll mult_mod(ll a,ll b,ll c)

 30 {

 31     a%=c;

 32     b%=c;

 33     ll ret=0;

 34     ll tmp=a;

 35     while(b)

 36     {

 37         if(b&1)

 38         {

 39             ret+=tmp;

 40             if(ret>c) ret-=c;

 41         }

 42         tmp<<=1;

 43         if(tmp>c) tmp-=c;

 44         b>>=1;

 45     }

 46     return ret;

 47 }

 48 

 49 ll pow_mod(ll a,ll n)

 50 {

 51     ll ret=1;

 52     ll temp=a%mod;

 53     while(n)

 54     {

 55         if(n&1)

 56         {

 57             ret=(ret*temp)%mod;

 58         }

 59         temp=(temp*temp)%mod;

 60         n>>=1;

 61     }

 62     return ret;

 63 }

 64 int main()

 65 {

 66     inti();

 67     while(scanf("%s",str)!=EOF)

 68     {

 69         int k=strlen(str);

 70         for(int i=1; i<=13; i++)

 71         {

 72             num[i]=4;

 73         }

 74         int cnt=52;

 75         for(int i=0; i<k; i++)

 76         {

 77             num[q[str[i]]]--;

 78             cnt--;

 79             if(str[i]=='1') i++;

 80         }

 81         ll ans=0;

 82         int m=cnt;

 83         bool flag=false;

 84         for(int i=0; i<k; i++)

 85         {

 86             if(cnt==0) break;

 87             for(int j=1; j<=13; j++)

 88             {

 89                 if(num[j]>0&&j<q[str[i]])

 90                 {

 91                     ll x=f[cnt-1];

 92                     ll y=1;

 93                     for(int c=1; c<=13; c++)

 94                     {

 95                         if(c==j)

 96                         {

 97                             y=(y*f[num[c]-1])%mod;

 98                             continue;

 99                         }

100                         y=(y*f[num[c]])%mod;

101                     }

102                     x=(x*pow_mod(y,mod-2))%mod;

103                     ans=(ans+x)%mod;

104                 }

105             }

106             if(num[q[str[i]]]==0)

107             {

108                 flag=true;

109                 break;

110             }

111             num[q[str[i]]]--;

112             cnt--;

113             if(str[i]=='1') i++;

114         }

115         if(!flag&&m<52-m)

116             ans=(ans+1)%mod;

117         printf("%lld\n",ans);

118     }

119     return 0;

120 }
View Code

 

你可能感兴趣的:(ZOJ)