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

时间: 2024-08-30 03:58:57

洛谷P2518 [HAOI2010]计数的相关文章

洛谷 P2807 三角形计数

P2807 三角形计数 题目背景 三角形计数(triangle) 递推 题目描述 把大三角形的每条边n等分,将对应的等分点连接起来(连接线分别平行于三条边),这样一共会有多少三角形呢?编程来解决这个问题. 输入输出格式 输入格式: 第一行为整数t(≤100),表示测试数据组数:接下来t行,每行一个正整数n(≤500). 输出格式: 对于每个n,输出一个正整数,表示三角形个数. 输入输出样例 输入样例#1: 复制 3 1 2 3 输出样例#1: 复制 1 5 13 说明 n(≤500) t(≤10

洛谷——P3914 染色计数

P3914 染色计数 题目描述 有一颗NN个节点的树,节点用1,2,\cdots,N1,2,?,N编号.你要给它染色,使得相邻节点的颜色不同.有MM种颜色,用1,2,\cdots,M1,2,?,M编号.每个节点可以染MM种颜色中的若干种,求不同染色方案的数量除以(10^9 + 7109+7)的余数. 输入输出格式 输入格式: 第1 行,2 个整数N,MN,M. 接下来NN行,第ii行表示节点ii可以染的颜色.第1个整数k_iki?,表示可以染的颜色数量.接下来k_iki?个整数,表示可以染的颜色

洛谷 P1176 路径计数2

P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1, 1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法. 但是这个问题太简单了,所以现在有M个格子上有障碍,即不能走到这M个格子上. 输入输出格式 输入格式: 输入文件第1行包含两个非负整数N,M,表示了网格的边长与障碍数. 接下来M行,每行两个不大于N的正整数x, y.表示坐标(x, y)上有障碍不能通过,且有1≤x, y≤n,且x, y至少有一个大于1,并请注意障碍坐标有可

洛谷 P2515 [HAOI2010]软件安装

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出一种

洛谷—— P2515 [HAOI2010]软件安装

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出一种

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

洛谷P1144 最短路计数(SPFA)

To 洛谷.1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输

洛谷 1144 最短路计数 bfs

洛谷1144 最短路计数 传送门 其实这道题目的正解应该是spfa里面加一些处理,,然而,,然而,,既然它是无权图,,那么就直接bfs了,用一个cnt记录一下每一个点的方案数,分几种情况讨论一下转移,最后输出cnt即为结果.. 题目中所说的重边和自环啥的没看出来有啥影响.. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int maxn = 100000 + 500;

洛谷P1061 Jam的计数法 数学

洛谷P1061 Jam的计数法 数学 已知一个字符串 其 均有 s--t构成 且字符串要求 s[ i ]<s[ j ] i < j 已知一个字符串 求按字典序排列 的后5个字符串 1. 对于一个字符串已知,我们如何求他的下一个字符串呢? 我们可以从低位枚举到高位,找到第一个可以增长的数,然后增长2.同时把自己后面的串改为字典序最小,即这一位为上一位 + 1 这样字典序就最小了 1 #include <cstdio> 2 #include <cmath> 3 #inclu