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;
}

原文地址:https://www.cnblogs.com/zhangjiuding/p/9221765.html

时间: 2024-10-15 22:16:42

Codeforces 991E. Bus Number (DFS+排列组合)的相关文章

Codeforces Gym 100187D D. Holidays 排列组合

D. Holidays Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/D Description Everyone knows that the battle of Endor is just a myth fabled by George Lucas for promotion of his movie. Actually, no battle of Endor has

dfs 排列组合——找所有子集

17. 子集 中文 English 给定一个含不同整数的集合,返回其所有的子集. 样例 样例 1: 输入:[0] 输出: [ [], [0] ] 样例 2: 输入:[1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ] 挑战 你可以同时用递归与非递归的方式解决么? 注意事项 子集中的元素排列必须是非降序的,解集必须不包含重复的子集. 时间复杂度是O(2^n),本质就是在做二叉树的dfs.[1,2,3]举例: root /  

Codeforces Round #491 (Div. 2) E - Bus Number + 反思

E - Bus Number 最近感觉打CF各种车祸.....感觉要反思一下, 上次读错题,这次想当然地以为18!肯定暴了longlong 而没有去实践, 这个题我看到就感觉是枚举每个数字的个数,但是我觉得算得时候会爆longlong 就想用大数,但是我去看别人交的全部都是C++,就感觉是不是有别的方法, 想了半天感觉时间来不及了就强行上了个java,结果时间来不及... 以后写题首先要读清楚题目,其次不要想当然,要去实践!!!!!!!!!!! 真的很烦. import java.math.Bi

[Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理)

[Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理) 题面 一个\(n \times n\)的格子,每个格子里可以填\([1,k]\)内的整数.要保证每行每列的格子上的数最小值为1,有多少种方案 \(n \leq 250,k \leq 10^9\) 分析 这题有\(O(n^3)\)的dp做法,但个人感觉不如\(O(n^2 \log n)\)直接用数学方法求更好理解. 考虑容斥原理,枚举有\(i\)行最小值>1,有\(j\)行最小值>1,那

Codeforces 55D Beautiful Number

Codeforces 55D Beautiful Number a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. Input The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two

排列组合问题的一些整理

初步:加法原理和乘法原理 概念: 加法原理是分类计数原理,常用于排列组合中,具体是指:做一件事情,完成它有n类方式,第一类方式有M1种方法,第二类方式有M2种方法,--,第n类方式有Mn种方法,那么完成这件事情共有M1+M2+--+Mn种方法. 做一件事,完成它需要分成n个步骤,做第一 步有m1种不同的方法,做第二步有m2种不同的方法,--,做第n步有mn种不同的方法.那么完成这件事共有 N=m1×m2×m3×-×mn 种不同的方法. 这个感觉大家都知道(小学奥数就开始学了吧qwq),感觉没有什

HDU--5396(区间dp+排列组合)

做这道题的时候,想到会不会是dp,然后发现dp可做,但是一直被自己坑到死. 枚举最后合并的那个位置,然后对于加减号的,分成的前后两个部分都有不同的组合方法, (a1+a2........) +  (b1,b2.............)         对于每个a,被加b的个数的阶乘次 ,对于每个b,被加a的个数的阶乘次 减法同理 乘法特殊一点 (a1+a2........) *  (b1,b2.............)  乘法分配率,直接将两部分的总和相乘即可 想到这些还远远没有结束,因为最

hdu 4465 Candy (快速排列组合 )

Candy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2115    Accepted Submission(s): 910 Special Judge Problem Description LazyChild is a lazy child who likes candy very much. Despite being ve

排列&组合

What's the Difference? In English we use the word "combination" loosely, without thinking if the order of things is important. In other words: "My fruit salad is a combination of apples, grapes and bananas" We don't care what order the