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

 

posted @ 2015-03-23 16:27  null1019  阅读(214)  评论(0编辑  收藏  举报