zoukankan      html  css  js  c++  java
  • 洛谷P2518 [HAOI2010]计数

    题目:https://www.luogu.org/problemnew/show/P2518

    题目描述

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

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    1020
    输出样例#1: 
    7

    说明

    n的长度不超过50,答案不超过2^63-1.

    解析

    这道题第一眼感觉可定和数学有关,但也有点像数位dp。

    这道题求的是在给定数中,全排列结果比目前数小的个数。

    那么可以利用数位的思维,一位一位的求。

    模仿数位dp中limit(即是否有最大值限制)的用法。

    设原数为a,第i位为a[i],长度为n。

    这个数中0~9 出现次数为tot[1],tot[2],tot[3]。。。。。。tot[9]。

    先从最高位n开始,现在尝试往最高位上放数x。

    如果0≤x<a[n],那么后面的数就没有限制了,在剩下的数中随便取。

    设这种情况的方案数怎么求?

    第一位为x确定,所以tot[x]--;

    我们考虑往剩下的n-1位中填数。

    0要填tot[0]次,1要填tot[1]次,...,9要填tot[9]次。

    我们先把0填上,那么填上0的方案数为c(n-1,tot[0]),

    (c为组合数)

    剩下只有n-1-tot[0]个位置了,

    所以填1的方案数位c(n-1-tot[0],tot[1]),

    以此类推,方案数遵循乘法原理,这种情况的方案数为:

    c(n-1,tot[0])*c(n-1-tot[0],tot[1])*...*c(n-1-tot[0]-tot[1]-...-tot[8],tot[9]);

    如果x==a[n],那么只要保证剩下n-1位全排列符合条件就可以。

    求剩下n-1位的方法就同 求n位的方法了。

    详情参照代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstring>
     7 using namespace std;
     8 #define ll long long
     9 string ra;
    10 ll a[100],n;
    11 ll tot[100],tmp,m;
    12 ll c[100][100];
    13 ll ans;
    14 void get_zuhe(){
    15     for (int i=0;i<=60;++i){
    16         c[i][0]=1;
    17     }
    18     for (int i=1;i<=60;++i){
    19         for (int j=1;j<=i;++j){
    20             c[i][j]=c[i-1][j]+c[i-1][j-1];
    21         }
    22     }
    23 }
    24 int main(){
    25     cin>>ra;
    26     n=ra.size();
    27     for (ll i=1;i<=n;++i){
    28         a[i]=ra[n-i]-'0';
    29         tot[a[i]]++;
    30     }
    31     get_zuhe();
    32     for (ll i=n;i>=1;--i){
    33         for (ll j=0;j<a[i];++j){
    34             if (tot[j]){
    35                 tot[j]--;
    36                 tmp=1; m=i-1;
    37                 for (ll k=0;k<=9;++k){
    38                     if (tot[k]){
    39                         tmp*=c[m][tot[k]];
    40                         m-=tot[k];
    41                     }
    42                 }
    43                 ans+=tmp;
    44                 tot[j]++;
    45             }
    46         }
    47         tot[a[i]]--;
    48     }
    49     cout<<ans;
    50     return 0;
    51 }
    View Code
  • 相关阅读:
    Amazon Route 53
    监控应用程序负载均衡器ALB
    DynamoDB 流
    DynamoDB 中的限制
    Amazon SNS 消息属性
    关于基于 SAML 2.0 的联合身份验证
    Amazon EBS 性能提示
    Laravel5.1注册中间件的三种场景
    编译LNMP环境
    傻瓜式搭建LAMP环境
  • 原文地址:https://www.cnblogs.com/gjc1124646822/p/8053002.html
Copyright © 2011-2022 走看看