Codeforces Round #491 (Div. 2):E. Bus Number(DFS+组合数)

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 nn.

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 202880222820 or just 820. However, numbers 802220852 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 nn, determine the total number of possible bus number variants.

Input

The first line contains one integer nn (1n10181≤n≤1018) — the number of the bus that was seen by Vasya. It is guaranteed that this number does not start with 00.

Output

Output a single integer — the amount of possible variants of the real bus number.

Examples
input
97
output
2
input
2028
output
13


题意:给你一个数字序列A(长度不超过18位),问有多少个序列B满足①A中所有数字都一定要在B中出现过;②B中所有数字也一定要在A中出现过;③序列B不能以0开头

思路:直接爆搜所有数字出现情况,然对于每种情况求出非0开头的全排列数量就ok


#include<stdio.h>
#define LL long long
char str[1005];
LL ans, num[22], a[22], jc[22] = {1};
void Sech(int x)
{
	LL i, now, p, sum;
	if(x==10)
	{
		now = 1, sum = 0;
		for(i=0;i<=9;i++)
		{
			now = now*jc[a[i]];
			sum += a[i];
		}
		now = jc[sum]/now;
		if(a[0]>=1)
		{
			p = jc[a[0]-1];
			for(i=1;i<=9;i++)
				p = p*jc[a[i]];
			now -= jc[sum-1]/p;
		}
		ans += now;
		return;
	}
	for(i=1;i<=num[x];i++)
	{
		a[x] = i;
		Sech(x+1);
	}
	if(num[x]==0)
		Sech(x+1);
}
int main(void)
{
	LL i;
	scanf("%s", str+1);
	for(i=1;i<=19;i++)
		jc[i] = jc[i-1]*i;
	for(i=1;str[i]!=0;i++)
		num[str[i]-'0']++;
	Sech(0);
	printf("%I64d\n", ans);
	return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值