zoukankan      html  css  js  c++  java
  • BZOJ2425: [HAOI2010]计数

    BZOJ2425: [HAOI2010]计数

    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.


    题解Here!

    这题思路和数位$DP$差不多。

    一位一位向前推进。

    首先我们知道,对于一个数,把其中的$0$删掉,相当于把$0$放到了前面。

    所以这个问题就是让我们求一下给我们的数字的全排列中比当前小的有几个。

    设$num[i]$代表数字$i(iin[0,9])$有几个。

    那么全排列就是这个式子:
    $$frac{(sum_{i=0}^9num[i])!}{prod_{i=0}^9num[i]!}$$

    当然如果$num[i]==0$那么不参与运算。。。

    但是这样的话$long long$表示存不下。

    我已经说了我不会再写高精度的!

    所以继续想优化。

    假设现在有$m$个位置。

    我们先把$0$放法放好:
    $$C_m^{num[0]}$$

    之后就只有$m-num[0]$个位置。

    然后再放$1$:
    $$C_{m-num[0]}^{num[1]}$$

    以此类推。。。

    所以答案长这个样:
    $$Ans=C_m^{num[0]} imes C_{m-num[0]}^{num[1]} imes... imes C_{m-num[0]-num[1]-...-num[8]}^{num[9]}$$

    然后这个组合数就用杨辉三角什么的乱搞就好了。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 1010
    using namespace std;
    int n,val[MAXN],num[MAXN];
    long long triangle[MAXN][MAXN];
    inline void read(){
    	char c=0;
    	n=0;
    	while(c<'0'||c>'9')c=getchar();
    	while(c>='0'&&c<='9'){val[++n]=c-'0';num[val[n]]++;c=getchar();}
    }
    long long C(long long n,long long m){
    	if(triangle[n][m])return triangle[n][m];
    	if(m==1)return n;
    	if(m==0||m==n)return 1;
    	if(m>n)return 0;
    	triangle[n][m]=C(n-1,m)+C(n-1,m-1);
    	return triangle[n][m];
    }
    long long solve(int x){
        long long s=1;
        for(int i=0;i<=9;i++)
        if(num[i]){
            s*=C(x,num[i]);
            x-=num[i];
        }
        return s;
    }
    void work(){
    	long long ans=0;
    	for(int i=1;i<=n;i++){
    	    for(int j=0;j<val[i];j++)
            if(num[j]){
                num[j]--;
                ans+=solve(n-i);
                num[j]++;
            }
            num[val[i]]--;
        }
        printf("%lld
    ",ans);
    }
    int main(){
    	read();
    	work();
        return 0;
    }
    
  • 相关阅读:
    序言vue.js介绍
    python中end=''
    python文件的操作
    python异常
    python异常(理论知识)
    Uva 11300 Spreading the Wealth 中位数
    反转(开关问题) poj3276
    NEKO's Maze Game 思维
    Aaronson 一道思维题
    我开博客了
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9492835.html
Copyright © 2011-2022 走看看