luogu2518 [HAOI2010] 计数
题目大意
给出一个数字$n$,求满足下列条件的数$x$的个数:
- $x<n$
- 对于来自于$x$十进制各个数位上的非零数字,它们的种类与个数都与$n$的相同。
思路
入手点
设$n$有$t$位数字,如果满足上述条件的$x$的位数$t'$比$t$小,那相当于$x$前面含有$t-t'$个前缀0!因此如果我们不考虑第1条,那么$x$就是由$n$各个位上数字包括0组成的全排列。
考虑第一条
我们定义$a_i$为数$n$在第$i$位上的数字,$b_i$则是$x$的。$f(m)$为当$n$与$x$在$m$以上的位数都相等的情况下,满足题目条件的排列个数。若$a_m=b_m$,则转化为子问题$f(m-1)$;如果$b_m<a_m$,则$x$位数比$m$小的那部分无论如何排列,都会满足第一条,故结果为:对于每一个$b_m\in[0,a_m)$,将其锁定在第$m$位,$n$在$m$及以下的位数的所有数字排除掉被安在第一位的$b_m$后,在$m-1$个数中的全排列。由加法原理,这些结果都要相加。
怎么求含可重元素的全排列
已知一个数组,$h_i$表示一个元素的个数,在长度$m$的区间里求它的全排列。其相当于先在区间中安0,共有$C_m^{h_0}$种选法;然后再在剩余的空间$m-h_0$中看看1的安放方式,即$C_{m-h_0}^{h_1}$。以此类推。根据乘法原理,这些组合数要相乘才为结果。
注意事项
- ans用long long!
- 求组合数递归时不要忘了给C数组赋值!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <cstdlib>
#include <iostream>
using namespace std; #define ll long long
const int MAX_DIGIT = 55, MAX_NUM = 10;
ll A[MAX_DIGIT];
int NumCnt[MAX_NUM];
ll C[MAX_DIGIT][MAX_DIGIT]; ll Comb(int n, int m)
{
if (n < 0 || m < 0)
return 0;
if (C[n][m])
return C[n][m];
else if (m == 0 || m == n)
return C[n][m] = 1;
else if (m == 1)
return C[n][m] = n;
else if (m > n)
return 0;
else
return C[n][m] = Comb(n - 1, m - 1) + Comb(n - 1, m);
} ll GetAns(const int len)
{
if (len == 1)
return 0;
ll ans = 0;
for (int firstNum = 0; firstNum < A[len]; firstNum++)
{
NumCnt[firstNum]--;
int subLen = len - 1;
ll combAns = 1;
for (int num = 0; num < 10; num++)
{
combAns *= Comb(subLen, NumCnt[num]);
subLen -= NumCnt[num];
}
NumCnt[firstNum]++;
ans += combAns;
}
NumCnt[A[len]]--;
ans += GetAns(len - 1);
return ans;
} int main()
{
stack<int> st;
char c;
while (cin >> c && isdigit(c))
st.push(c - '0');
int len = 0;
while (!st.empty())
{
A[++len] = st.top();
NumCnt[A[len]]++;
st.pop();
}
cout << GetAns(len) << endl;
return 0;
}
luogu2518 [HAOI2010] 计数的更多相关文章
- 【BZOJ2425】[HAOI2010]计数(组合数学)
[BZOJ2425][HAOI2010]计数(组合数学) 题面 BZOJ 洛谷 题解 很容易的一道题目. 统计一下每个数位出现的次数,然后从前往后依次枚举每一位,表示前面都已经卡在了范围内,从这一位开 ...
- bzoj 2425 [HAOI2010]计数 dp+组合计数
[HAOI2010]计数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 451 Solved: 289[Submit][Status][Discus ...
- BZOJ2425: [HAOI2010]计数
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2425 其实能够构成的数就是原数的排列(算前导0),然后组合计数一下就可以了. #include ...
- P2518 [HAOI2010]计数
题目链接 \(Click\) \(Here\) 很好很妙的一个题目. 其实可以生成的数字,一定是原数的一个排列,因为\(0\)被放在前面就可以认为不存在了嘛~.也就是说现在求的就是全排列中所有小于该数 ...
- bzoj千题计划178:bzoj2425: [HAOI2010]计数
http://www.lydsy.com/JudgeOnline/problem.php?id=2425 题意转化: 给定一个集合S,求S的全排列<给定排列 的排列个数 从最高位开始逐位枚举确定 ...
- BZOJ2425:[HAOI2010]计数(数位DP)
Description 你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1 ...
- [HAOI2010]计数(组合数学)(数位DP)
原题题意也就是给的数的全排列小于原数的个数. 我们可以很容易的想到重复元素的排列个数的公式. 但是我们发现阶乘的话很快就会爆long long啊(如果您想写高精请便) 之后我就尝试质因数分解....但 ...
- [HAOI2010]计数 数位DP+组合数
题面: 你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等. ...
- BZOJ2425:[HAOI2010]计数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2425 https://www.luogu.org/problemnew/show/P2518 你有 ...
随机推荐
- JavaScript 判断手机端操作系统(Andorid/IOS)
androidURL = "http://xxx/xxx.apk"; var browser = { versions: function() { var u = navigato ...
- jQuery学习笔记之DOM操作、事件绑定(2)
jQuery学习笔记之DOM操作.事件绑定(2) --------------------学习目录------------------------ 4.DOM操作 5.事件绑定 源码地址: https ...
- java Web(2)
Servlet与web容器的配合: 1)客户端向Web服务器发起一个HTTP请求. 2)HTTP请求被Web服务器接受,如果请求的是静态页面,则由Web服务器负责处理.如果请求的是Java Web组件 ...
- ROS:Nvidia Jetson TK1开发平台
原文链接: http://wiki.ros.org/NvidiaJetsonTK1 1. Nvidia Jetson TK1 Jetson TK1 comes pre-installed with L ...
- Linux 之WinSCP连接FTP
1.安装vsftpd 2.ftp命令 /sbin/service vsftpd start /sbin/service vsftpd restart /sbin/service vsftpd stop ...
- Jmeter JSON断言和响应断言的区别是什么?
假设响应数据是{"code":0,"datas":{"informationStatus":1}} 响应断言:"code" ...
- 安装mysql遇到的几个坑
1. 官网下载压缩版mysql,配置太复杂 弃之 2. 官网下载最新版本mysql安装包 5.8.X,安装成功,一路next,安装成功后发现没有看到自定义安装路径,查看mysql安装完成的路径果然在C ...
- 团体程序设计天梯赛-练习集-L1-047. 装睡
L1-047. 装睡 你永远叫不醒一个装睡的人 —— 但是通过分析一个人的呼吸频率和脉搏,你可以发现谁在装睡!医生告诉我们,正常人睡眠时的呼吸频率是每分钟15-20次,脉搏是每分钟50-70次.下面给 ...
- javaee字符缓冲输出流
package Zjshuchu; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOExcepti ...
- Linux文件压缩命令笔记
1.gzip/gunzip gzip/gunzip:主要是进行单个文件的压缩和解压缩的命令. 示例:gzip hello.txt #执行压缩hello.txt ls hello.txt.gz #查看文 ...