BZOJ2425 [HAOI2010]计数

比较简单的数位dp,但是要用到组合公式C,预处理吧。。。

 1 /**************************************************************
 2     Problem: 2425
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:0 ms
 7     Memory:828 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <algorithm>
12 #include <cstring>
13
14 using namespace std;
15 typedef long long ll;
16 const int N = 55;
17 ll ans, c[N][N];
18 int num[10];
19 char s[N];
20 int n;
21
22 ll calc(int x){
23     ll res = 1;
24     for (int i = 0; i <= 9; ++i)
25         res *= c[x][num[i]], x -= num[i];
26     return res;
27 }
28
29 int main(){
30     scanf("%s", s + 1);
31     n = strlen(s + 1);
32     c[0][0] = 1;
33     for (int i = 0; i <= n; ++i)
34         for (int j = 0; j <= i; ++j)
35             c[i + 1][j] += c[i][j], c[i + 1][j + 1] += c[i][j];
36     for (int i = 1; i <= n; ++i)
37         ++num[s[i] - ‘0‘];
38     ans = 0;
39     for (int i = 1; i <= n; ++i){
40         for (int j = 0; j < s[i] - ‘0‘; ++j)
41             if (num[j]){
42                 --num[j];
43                 ans += calc(n - i);
44                 ++num[j];
45             }
46             --num[s[i] - ‘0‘];
47     }
48     printf("%lld\n", ans);
49     return 0;
50 }

时间: 2024-10-01 07:10:28

BZOJ2425 [HAOI2010]计数的相关文章

BZOJ2425 [HAOI2010]计数 【数位dp】

题目 你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等. 现在给定一个数,问在这个数之前有多少个数.(注意这个数不会有前导0). 输入格式 只有1行,为1个整数n. 输出格式 只有整数,表示N之前出现的数的个数. 输入样例 1020 输出样例 7 提示 n的长度不超过50,答案不超过\(2^{63}-1\). 题解 如果我们看做把0删除看做把0前导,那么问题

[HAOI2010] 计数 - 数位dp,组合数

你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等. 现在给定一个数,问在这个数之前有多少个数.(注意这个数不会有前导0). Solution 可重复康托展开 常用数位 dp 套路,枚举哪一位开始比原数小,前方唯一而后方算全排列 回避高精度的全排列数计算,考虑到阶乘最多大约算到 50, 开个因子计数桶,然后在桶上操作就可以了 #include <bits/st

[haoi2010]计数

你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,10200,等等.现在给定一个数,问在这个数之前有多少个数.(注意这个数不会有前导0). 基础数位dp之一: 普通dp思路: 首先想到设状态,怎么设呢?设的状态肯定要把前面用了多少数表示出来,按照这个思路就只能设f[i][j]表示在第i位,j是所有非0数字的二进制表示: 然后可以记忆化搜索进行转移: 这个方法可以过(HA的数

洛谷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:

BZOJ 2425 [HAOI2010]计数:数位dp + 组合数

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2425 题意: 给你一个数字n,长度不超过50. 你可以将这个数字: (1)去掉若干个0 (2)打乱后重新排列 问你可以产生多少个小于n的数字. 题解: 题目中的第一个操作其实是没有用的. 去掉若干个0之后再重新排列(不允许前导0),和不去0直接重新排列(允许前导0),其实是等价的. 所以按照数位dp的方法从高到低按位统计. 如n = 2345时,分别统计前缀为0~1, 20~22, 23

bzoj 2425 [HAOI2010]计数 数学

题面 题目传送门 解法 显然可以一位一位确定答案 假设在第\(i\)时已经比原数小了,那么答案就可以加上\(\frac{(n-i)!}{s_0!s_1!-s_9!}\) 但是因为\(n≤50\),所以可能会爆long long,需要高精度 然而我就十分sb地写了高精度-- 其实并不需要用高精度啊 可以先确定0放置的方案,在剩下的里面1的方案,-- 然后对这个东西不断乘起来就好了,就是一个组合数的问题 代码(sb的高精度) #include <bits/stdc++.h> using names

P2518 [HAOI2010]计数

题目描述 你有一组非零数字(不一定唯一),你可以在其中插入任意个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. Soluti

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

数位dp初探

我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了很久TAT #include<cstring> #include<iostream> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> #define