• 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;	
    }
    
  • 相关阅读:
    继续致歉
    向大家致歉!!
    访问速度调查
    致歉
    [功能改进]通过Blog客户端直接发随笔至网站分类
    带宽升级公告
    创业团队的类型
    [讨论]基于.NET的开源论坛软件的选择
    调整一下工作的节奏
    公告
  • 原文地址:https://www.cnblogs.com/zhangjiuding/p/9221765.html
Copyright © 2020-2023  润新知