bzoj 2425 [HAOI2010]计数 dp+组合计数
[HAOI2010]计数
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
这个就是一个简单的组合计数问题。
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 }