• Light OJ 1060


    题目大意:

    给你一个字符串,问这个字符串按照特定顺序排列之后,第n个字符串是哪个?

    题目分析:

    首先我们要会求解总个数。也就是共有len个字符,每个字符有ki个,那么总组合方式是多少种?

    总组合方式就是: (len!)/(ki !), 把每个ki的阶乘都除一边,最后算出的结果就是答案了。

    那么问题就剩下解决第n个字符串的的问题了。

    下面我们先了解一下排序计数:

    排序计数

    • 如1,2,3,4的全排列,共有4!种,求第10个的排列是(从1计起)?
    • 先试首位是1,后234有3!=6种<10,说明首位1偏小,问题转换成求2开头的第(10-6=4)个排列,而3!=6 >= 4,说明首位恰是2。
    • 第二位先试1(1没用过),后面2!=2个<4,1偏小,换成3(2用过了)为第二位,待求序号也再减去2!,剩下2了。而此时2!>=2,说明第二位恰好是3。
    • 第三位先试1,但后面1!<2,因此改用4。末位则是1了。
    • 这样得出,第10个排列是2-3-4-1。

    然后求解方法和上面阶乘的方法大同小异。

    =============================================================================================================

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #include<vector>
     8 #include<map>
     9 using namespace std;
    10 typedef long long LL;
    11 const int INF = 1e9+7;
    12 const int MAXN = 555;
    13 int vis[30];
    14 char str[50];
    15 LL Fact[25], n;
    16 
    17 void DFS(int pos,LL num)
    18 {
    19     if(pos == 0)
    20     {
    21         printf("
    ");
    22         return ;
    23     }
    24 
    25     for(int i=0; i<26; i++)
    26     {
    27         if(vis[i] == 0) continue;
    28 
    29         LL temp = Fact[pos-1]*vis[i];
    30 
    31         for(int j=0; j<26; j++)
    32             temp /= Fact[vis[j]];
    33         if(num > temp)
    34             num -= temp;
    35         else
    36         {
    37             vis[i] --;
    38             printf("%c", 'a'+i);
    39             break;
    40         }
    41 
    42     }
    43     DFS(pos-1, num);
    44 }
    45 
    46 
    47 int main()
    48 {
    49     int T, cas = 1;
    50     Fact[0] = 1;
    51     for(int i=1; i<=22; i++)
    52     Fact[i] = Fact[i-1] * i;
    53     scanf("%d", &T);
    54 
    55     while(T --)
    56     {
    57         scanf("%s %lld",str, &n);
    58 
    59         memset(vis, 0, sizeof(vis));
    60         int len = strlen(str);
    61         for(int i=0; str[i]; i++)
    62             vis[str[i] - 'a'] ++;
    63         LL ans = Fact[len];
    64 
    65         printf("Case %d: ", cas ++);
    66         for(int i=0; i<26; i++)
    67             ans /= Fact[vis[i]];
    68 
    69         if(ans < n)
    70             puts("Impossible");
    71         else
    72             DFS(len, n);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    git
    浏览器喧嚷过程
    B/S架构与C/S架构
    simpleDateFormat
    oracle中case when的用法
    Java程序利用Jdbc连接数据库
    List 和 Set与Map
    队列和栈
    toString方法分析
    java中的构造器
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4920504.html
Copyright © 2020-2023  润新知