Codeforces 991E. Bus Number (DFS+排列组合)

解题思路

  1. 将每个数字出现的次数存在一个数组num[]中(与顺序无关)。
  2. 将出现过的数字i从1到num[i]遍历。(i from 0 to 9)
  3. 得到要使用的数字次数数组a[]。
  4. 对于每一种a使用排列组合公式:
    这里写图片描述
  5. ans += 上面那个公式。(每用一次这个公式对应一个a)

##排列组合公式注解

  1. 减号左边表示的是sum个数字全排列并去重。
  2. 减号右边表示的是从a[0]中选出一个0当做第一个数字,并对其他数字全排列并去重。

抱歉,写的可能比较混乱,还有部分细节需要读者处理。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

string s;
int num[10];
ll jc[20];//阶乘 
int tempNum[10];
ll ans = 0;

void dfs(int x){
	//如果0~9都填充好了数字 
	if(x == 10){
		//cnt表示所有数字的个数 
		int cnt = 0;
		for(int i = 0;i < 10; ++i){
			cnt += tempNum[i];
		}
		//排列组合公式 开始 
		ll p = jc[cnt];
		for(int i = 0;i < 10; ++i){
			p /= jc[tempNum[i]];
		}
		if(tempNum[0] >= 1)
			p -= (p*tempNum[0]/cnt);
		//排列组合公式 结束 
		ans += p;
		return ;
	}
	//对于出现过的数字,个数从1开始 
	for(int i = 1;i <= num[x]; ++i){
		tempNum[x] = i;
		dfs(x+1);
	}
	if(num[x] == 0){
		dfs(x+1);
	}
}


int main(){
	ios::sync_with_stdio(false);
	cin >> s;
	for(auto i:s) num[i-'0']++;
	//算阶乘 
	jc[0] = 1;
	for(ll i = 1;i <= 19; ++i){
		jc[i] = jc[i-1]*i;
	}
	dfs(0);
	cout << ans << endl;
	return 0;	
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ninding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值