Concise and clear CodeForces - 991F(dfs 有重复元素的全排列)

就是有重复元素的全排列

#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
const int maxn = 10010, INF = 0x7fffffff;
char str[maxn];
int vis[maxn], v[maxn];
LL num[maxn];
LL res = 0;
void init()
{
    num[0] = 1;
    for(int i=1; i<maxn; i++)
        num[i] = num[i-1] * i;
}
void dfs(LL x, LL cnt)
{
    if(cnt == 10)
    {
        if(x > 0) return;
        LL ans1 = 1, ans2 = 0, ans3 = 1;
        for(int i=0; i<=9; i++)
        {
            ans2 += v[i];
        }
        LL temp = ans2;
        ans2 = num[ans2];
        for(int i=0; i<=9; i++)
            ans2 /= num[v[i]];
    //    cout<< ans2 <<endl;
        if(v[0])
        {
            ans3 = num[temp-1];
            for(int i=0; i<=9; i++)
                if(i == 0) ans3 /= num[v[i]-1];
                else ans3 /= num[v[i]];

            ans2 -= ans3;
        }

        res += ans2;
        return;
    }
    if(!vis[cnt])
        dfs(x, cnt+1);
    else
        for(int i=0; i<vis[cnt] && i<=x; i++)
        {
            v[cnt] += i;
            dfs(x-i, cnt+1);
            v[cnt] -= i;
        }
}
int main()
{
    init();
    cin>> str;
    int len = strlen(str);
    int maxx = -INF;
    LL sum = 0, ans = 0, flag = 0;
    for(int i=0; i<len; i++)
    {
        if(i != 0)
            if(str[i] != str[i-1])
                flag = 1;
        vis[str[i]-‘0‘]++;
        if(vis[str[i]-‘0‘] == 1) ans++;
    }
    if(!flag)
    {
        cout<< len <<endl;
        return 0;
    }
    res += num[ans];
    if(vis[0])
        res -= num[ans-1];
    for(int i=0; i<=9; i++)
        if(vis[i])
            sum += vis[i]-1;
    for(int i=1; i<=sum; i++)
    {
        for(int i=0; i<=9; i++)
            if(vis[i])
                v[i] = 1;
            else
                v[i] = 0;
        dfs(i, 0);

    }
    cout<< res <<endl;

    return 0;
}

原文地址:https://www.cnblogs.com/WTSRUVF/p/9556318.html

时间: 2024-10-27 13:51:00

Concise and clear CodeForces - 991F(dfs 有重复元素的全排列)的相关文章

九章算法面试题54 带重复元素的全排列

九章算法官网-原文网址 http://www.jiuzhang.com/problem/54/ 题目 给定一个带重复元素的整数集合,求出这个集合中所有元素的全排列.对于集合[1,1,2],其本质不同的全排列有三个,分别为: [1,1,2] [1,2,1] [2,1,1] 在线测试本题 http://lintcode.com/problem/unique-permutations/ 解答 首先做这个题目之前,要先会不带重复元素的全排列. 程序参考:http://www.ninechapter.co

poj3421 X-factor Chains(重复元素的全排列)

poj3421 X-factor Chains 题意:给定正整数$x(x<=2^{20})$,求$x$的因子组成的满足任意前一项都能整除后一项的序列的最大长度,以及满足最大长度的子序列的个数. 显然最大长度就是$x$的质因数个数(一个一个加上去鸭) 而满足最大长度的子序列个数.... 这不就是可重复元素的全排列吗! 有这么一个公式,设元素总个数$n$,每个重复元素的个数$m_{i}$,共$k$种不同元素 则全排列个数$=\frac{n!}{\prod_{i=1}^{k}m_{i}!}$ 发现$n

减治求有重复元素的全排列

求n个元素的全排列的所有解可以用减治法:每次拎出一个数做前缀,对剩下的元素再求全排列,直至只剩一个元素.代码源自<算法分析与设计(王晓东)>,复杂度O(n2) 1 //输出k~m的所有全排列 2 void perm(int k,int m) 3 { 4 if(k==m) 5 { 6 for(int i=0;i<=m;i++) 7 printf("%d ", list[i]); 8 printf("\n"); 9 }else 10 { 11 for(

有重复元素的全排列

问题: 有k个元素,其中第i个元素有ni个,求全排列个数 分析: 令所有ni之和为n,设答案为x 首先做全排列, 然后把所有元素编号 其中第s中元素编号为1~ns 由于编号后所有元素均不相同,方案总数为n的全排列数n! n1!n2!n3!...nk!x=n! 移项即可 原文地址:https://www.cnblogs.com/darlingroot/p/10388821.html

刷题——有重复元素的全排列(Permutations II)

题目如上所示. 我的解决方法(参考了九章的答案!): class Solution { public: /* * @param : A list of integers * @return: A list of unique permutations */ vector<vector<int>> permuteUnique(vector<int> &nums) { vector<vector<int>> results; vector&l

Add Again(重复元素排序)

Add Again Input: Standard Input Output: Standard Output Summation of sequence of integers is always a common problem in Computer Science. Rather than computing blindly, some intelligent techniques make the task simpler. Here you have to find the summ

poj 3411 Paid Roads(dfs,可重复访问节点)

http://poj.org/problem?id=3411 大致题意:n个城市由m条公路连接,两个城市之间可能有多条公路连接.经过每条公路都需要收费,对于城市a,b,若之前经过城市c那么只需交p元钱,否则交r元钱.问从城市1到n的最小花费. 思路:由于经过每条公路的收费有两种方式,那么有的城市可能要经过多次,以便获得更小的花费,但也有可能出现有环的情况,那么该城市经过多次只会徒增花费.所以我们定义vis[]数组标记该城市访问的次数,在该题中(m <= 10)当一个城市访问超过3次(网上说这个与

Codeforces 405E DFS

这个题目要求把一个无向连通图里面的所有边,分成 两个一对,只能出现一次,而且一对边必须是连在一起的,点可以复用  但边不可复用 可解条件很易得,因为图是连通的,只要边数为偶数即可. 一开始我借着做欧拉回路的方法,直接DFS暴搜,沿路做标记,遇到未标记的连续两条边 输出即可 不过 事实证明这个算法是错的 暴搜能成立只是建立在图上的边可以存在很多个边对里,但肯定有图不满足这种条件 其实解决方法也就是在DFS的基础上对特殊边进行下考虑即可 即每次对某个点,对子节点进行dfs,如果发现子节点下面有落单的

两种方法删除ArrayList里重复元素

方法一: /** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); } 方法二: /** List order maintained **/ public static void removeDuplicateWithOrder(Arra