Codeforces G. Bus Number(dfs排列)
题目描述:
Bus Number
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
This night wasn't easy on Vasya. His favorite team lost, and he didn't find himself victorious either — although he played perfectly, his teammates let him down every time. He had to win at least one more time, but the losestreak only grew longer and longer... It's no wonder he didn't get any sleep this night at all.
In the morning, Vasya was waiting the bus to the university on the bus stop. Vasya's thoughts were hazy and so he couldn't remember the right bus' number quite right and got onto the bus with the number n.
In the bus, Vasya thought that he could get the order of the digits in the number of the bus wrong. Futhermore, he could "see" some digits several times, but the digits he saw were definitely in the real number of the bus. For example, if Vasya saw the number 2028, it could mean that the real bus number could be 2028, 8022, 2820 or just 820. However, numbers 80, 22208, 52 definitely couldn't be the number of the bus. Also, real bus number couldn't start with the digit 0, this meaning that, for example, number 082 couldn't be the real bus number too.
Given n, determine the total number of possible bus number variants.
Input
The first line contains one integer n(1≤n≤1018) — the number of the bus that was seen by Vasya. It is guaranteed that this number does not start with 0
Output
Output a single integer — the amount of possible variants of the real bus number.
Examples
Input
Copy
97
Output
Copy
2
Input
Copy
2028
Output
Copy
13
Note
In the first sample, only variants 97 and 79 are possible.
In the second sample, the variants (in the increasing order) are the following: 208
,280 , 802, 820,2028, 2208, 2280,2802,2820, 8022, 8202,8220
思路:
题目的意思是各一个数,数字里面的每个数至少使用一次,求用这些数字最多可以组成多少个开头不为零的数。
刚开始一个直白的想法就是,肯定要统计每个数字出现的次数,然后呢?
开始计算样例:0228,假如每个数只是用一次,028,可以组成\(A_3^3-A_2^2=4\)种数字,前面是所有数的全排列,后面减去开头为零的排列。然后可以使用两次,,0228,可以组成\(\frac{A_4^4}{A_2^2}-\frac{A_3^3}{A_2^2}\)种,因为有重复计算,所以会除以重复数字的全排列。
关键在于,我怎么知道什么时候该那个数字使用几次?
这时候,神奇的dfs就登场啦!可以用dfs搜索枚举所有的选择可能,把每一种的可能结果加起来就是最后的答案。我们来看一看,最后计算需要那几样东西。首先需要用了几个数字组成整个数,还要记录使用过每种数字的次数以便计算重复量。于是我们可以拿一个数组[10]来记录数字的使用情况,在dfs的时候,\(1.\)对于在原数中出现次数大于等于一的数字至少选一次,直到选完,进行更深一层的dfs。\(2.\)对于没有在原数中出现的数字,直接进行下一轮dfs。直到用到数字9完后来到10,因为没有数字了就可以终止该层递归,依照上面的计算方法计算,返回。
最后,得到的就是所有选取情况下的数字的可能性了。
需要注意的是由于数很大,要开long long,我开始在dfs返回时不小心把返回类型设成了int,还有因为排列数的计算要用到阶乘,一共只有最多18位数,可以方便地先预处理出20位的阶乘存起来。
代码:
#include <iostream>
#include <string>
using namespace std;
string s;
int cnt[10];
int used[10];
long long fac[21];
long long cishu = 0;//这个参数是我想看看进行了几次递归,神奇的发现次数比想象中的少,不知道为什么
void generator()//阶乘预处理
{
fac[0]=fac[1]=1;
for(int i = 2;i<=20;i++)
{
fac[i] = (long long)i*fac[i-1];
}
}
long long dfs(int x,int y)
{
cishu++;//递归一次次数加一
//cout << "x " << x << " y " << y << endl;
if(x==10)
{
long long ans = 0;
ans += fac[y];
for(int i = 0;i<10;i++)
{
/*if(used[i])
{
cout << "i" << i << "used " << used[i] << endl;
}*/
ans /= fac[used[i]];
}
long long zero = 0;//减去0开头的数的可能情况
if(used[0])
{
int num = y-1;
zero += fac[num];
zero /= fac[used[0]-1];
for(int i = 1;i<10;i++)
{
zero /= fac[used[i]];
}
}
//cout << "ans " << ans << " zero " << zero << endl;
return ans-zero;
}
long long ans = 0;
for(int i = 1;i<=cnt[x];i++)
{
used[x] = i;
ans += dfs(x+1,y+i);
}
if(cnt[x]==0)
{
ans += dfs(x+1,y);
}
return ans;
}
int main()
{
generator();
/*for(int i = 0;i<=20;i++)
{
cout << fac[i] << " ";
}
cout << endl;*/
cin >> s;
for(int i = 0;i<s.size();i++)
{
cnt[s[i]-'0']++;
}
//cout << "cnt " << endl;
/*for(int i = 0;i<10;i++)
{
cout << cnt[i] << " ";
}
cout << endl;*/
long long ans = dfs(0,0);
cout << ans << endl;
//cout << cishu << endl;
return 0;
}
Codeforces G. Bus Number(dfs排列)的更多相关文章
- Codeforces 991E. Bus Number (DFS+排列组合)
解题思路 将每个数字出现的次数存在一个数组num[]中(与顺序无关). 将出现过的数字i从1到num[i]遍历.(i from 0 to 9) 得到要使用的数字次数数组a[]. 对于每一种a使用排列组 ...
- Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS
G. Xor-matic Number of the Graph http://codeforces.com/problemset/problem/724/G 题意:给你一张无向图.定义一个无序三元组 ...
- Codeforces Round #491 (Div. 2) E - Bus Number + 反思
E - Bus Number 最近感觉打CF各种车祸.....感觉要反思一下, 上次读错题,这次想当然地以为18!肯定暴了longlong 而没有去实践, 这个题我看到就感觉是枚举每个数字的个数,但是 ...
- Codeforces 55D Beautiful Number
Codeforces 55D Beautiful Number a positive integer number is beautiful if and only if it is divisibl ...
- Cut 'em all! CodeForces - 982C(贪心dfs)
K - Cut 'em all! CodeForces - 982C 给一棵树 求最多能切几条边使剩下的子树都有偶数个节点 如果n是奇数 那么奇数=偶数+奇数 不管怎么切 都会有奇数 直接打印-1 贪 ...
- CF 724 G. Xor-matic Number of the Graph
G. Xor-matic Number of the Graph 链接 题意: 给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s, ...
- Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) G - Xor-matic Number of the Graph 线性基好题
G - Xor-matic Number of the Graph 上一道题的加强版本,对于每个联通块需要按位算贡献. #include<bits/stdc++.h> #define LL ...
- Codeforces 116C - Party(dfs)
n个人,每个人之多有一个上司.“上司”关系具有传递性.求最少将人分成多少组,每组中的每个人的上司或者间接上司都不在该组.拿到题就用树的直径wa了一炮... 正解是有向无环森林的最长路.从每个跟节点df ...
- UVA10624 - Super Number(dfs)
题目:UVA10624 - Super Number(dfs) 题目大意:给你n和m要求找出这种m位数,从第n位到第m位都满足前i位是能够被i整除,假设没有这种数,输出-1.有多个就输出字典序最小的那 ...
随机推荐
- C++17新特性optional和string_view
1. optional的作用 类模板 std::optional 管理一个可选的容纳值,即可以存在也可以不存在的值. 一种常见的 optional 使用情况是一个可能失败的函数的返回值.与其他手段,如 ...
- [ ceph ] CEPH 部署完整版(CentOS 7 + luminous)
1. 前言 拜读了 胖哥的(el7+jewel)完整部署 受益匪浅,目前 CEPH 已经更新到 M 版本,配置方面或多或少都有了变动,本博文就做一个 ceph luminous 版本完整的配置安装. ...
- nvarchar, varchar, nchar, char的差別
1. var,意思是可變動的,因為欄位長度可變動,所以會額外花費2Byte去儲存地址2. n,支援UNICODE UCS-2字元,因為萬國編碼(支援中文字),所以1字儲存2Byte nvarchar: ...
- WEBSHELL-恶意代码检测
静态查杀 提取特征写成规则库,调用规则库查杀.基于规则,会比较快,但漏报.误报会比较明显,一般的Webshell一句话木马变形混淆会比较多. yara规则 $eval = /(<\?php|[; ...
- Gerrit - 代码评审工具Gerrit简介与安装
1 - 前言 Code Review 代码评审是指在软件开发过程中,对源代码的系统性检查,改进代码质量,查找系统缺陷,保证软件总体质量和提高开发者自身水平. 简单的说,Code Review是用来确认 ...
- svg可视化制作工具
svg可视化制作工具直接ai里面用钢笔路径画好 然后右键建立复合路径 最后存储为svg即可 这样生成的svg就带path标签了
- mysql求中位数
实例1: SET @ID = 0; SELECT AVG(loan_amount) from ( SELECT @ID:=@ID+1 as ID, loan_amount FROM table_x ...
- AtCoder-arc058(题解)
A - こだわり者いろはちゃん / Iroha's Obsession(暴力) 题目链接 题目大意: 给你 \(k\) 个个位数字和一个数字 \(n\) ,要求找到一个大于等于n的数字,使得不出现 \ ...
- UML交互图
UML 交互图主要包括对象和消息两类元素,创建交互图的过程实际上就是向对象分配任务的过程,是可视化系统的交互行为. UML 交互图包括两种:序列图和协作图. 序列图:显示对象之间的关系,强调对象之间消 ...
- DRF框架(七) ——三大认证组件之频率组件、jwt认证
drf频率组件源码 1.APIView的dispatch方法的 self.initial(request,*args,**kwargs) 点进去 2.self.check_throttles(re ...