bzoj 2425 [HAOI2010]计数 dp+组合计数

[HAOI2010]计数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 451  Solved: 289
[Submit][Status][Discuss]

Description

你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数。比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等。

现在给定一个数,问在这个数之前有多少个数。(注意这个数不会有前导0).

 

 

Input

只有1行,为1个整数n.

 

 

Output

只有整数,表示N之前出现的数的个数。

 

Sample Input

1020

Sample Output

7

HINT

 

n的长度不超过50,答案不超过263-1.


 

 

Source

Day2

 

这个就是一个简单的组合计数问题。
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<algorithm>
 6 
 7 #define N 57
 8 #define ll long long
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 int n;
19 int cnt[N];
20 ll ans,c[N][N];
21 char ch[N];
22 
23 void init_C()
24 {
25     c[0][0]=1;
26     for (int i=1;i<=50;i++)
27     {
28         c[i][0]=1;
29         for (int j=1;j<=i;j++)
30             c[i][j]=c[i-1][j-1]+c[i-1][j];
31     }
32 }
33 ll cal(int x)
34 {
35     ll res=1;
36     int now=x;
37     for (int j=0;j<9;j++)
38         res*=c[now][cnt[j]],now-=cnt[j];
39     return res;
40 }
41 int main()
42 {
43     init_C(),scanf("%s",ch+1),n=strlen(ch+1);
44     for (int i=1;i<=n;i++) ++cnt[ch[i]-'0'];
45     for (int i=1;i<=n;i++)
46     {
47         for (int j=0;j<=(ch[i]-'0')-1;j++)
48             if (cnt[j])
49             {
50                 --cnt[j];
51                 ans+=cal(n-i);
52                 ++cnt[j];
53             }
54         --cnt[ch[i]-'0'];
55     }
56     printf("%lld\n",ans);
57 }

 

posted @ 2018-04-08 16:30  Kaiser-  阅读(139)  评论(0编辑  收藏  举报