• UVa 11027


    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=115&page=show_problem&problem=1968


    题目大意是,给你一串字符串,输出它的字典序的第n个回文字符串。如果没有或者没有n这么大的就输出“XXX”。


    首先先考虑能不能构成回文串,首先奇数个的字母肯定只能有1个,不然肯定不能没办法构成回文串。然后要得到一个回文串,只需要算出(strlen(str)>> 1)这么长的字符串就行了,然后看看是否存在个数为奇数的字母,最后把算出来的字符串反向输出一下就OK了。

    本来是打算用康托展开的,后来考虑到重复的元素是否能将重复的字母看成不重复的来算,最后花了一个下午,得出结论,不行。

    最后百度了下,看了题解,原来要用搜索来做。

    首先先计算一下所有的字母的个数,然后每个字母的个数直接除以2,用这个计算字符串的总排列数。接下来就直接搜索每一位,比如说对于第一位,先取出字典序最小的字母,计算第一个位置为这个字母的情况下又多少种排列数,比如说是k,如果k >= n,那么这个位置就可以确定下来了,如果k < n,, 那么这个位置放这个字母显然是不够的,需要放更大的字典序的字母进来,在继续找之前还要进行一步操作, n -= k, 因为如果对一个字符串进行全排列,肯定先排完第一个位置放字典序为最小的字母,然后才开始字典序第二大的。一直这样进行下去,这个字符串就搜索出来了。在这里写了个递归的代码,后来又改成了非递归的。

    上代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 using namespace std;
      4 typedef long long LL;
      5 const int MAXN = 30 + 5;
      6 
      7 LL fact[16];
      8 char OddChar;
      9 int n, len, num[26];
     10 char str[MAXN], ans[MAXN];
     11 
     12 //计算有多少种
     13 LL Permutation(int len)
     14 {
     15     LL res = fact[len];
     16 
     17     for(int i = 0; i < 26; ++i)
     18         res /= fact[num[i]];
     19 
     20     return res;
     21 }
     22 
     23 LL MaxPalindromic()
     24 {
     25     memset(num, 0, sizeof(num));
     26 
     27     for(int i = 0; str[i] != ''; ++i)
     28         ++num[str[i] - 'a'];
     29 
     30     int OddNum = 0;
     31 
     32     for(int i = 0; i < 26; ++ i)
     33     {
     34         if(num[i] & 1)
     35         {
     36             ++OddNum;
     37             OddChar = i + 'a';
     38         }
     39 
     40         num[i] >>= 1;
     41     }
     42 
     43     if(OddNum > 1)
     44         return 0LL;
     45 
     46     if(OddNum == 0)
     47         OddChar = '#';
     48 
     49     len = strlen(str) >> 1;
     50     return Permutation(len);
     51 }
     52 
     53 void solve(LL x, int n)
     54 {
     55     for(int i = 0; i < len; ++ i)
     56         for(int j = 0; j < 26; ++ j)
     57             if(num[j])
     58             {
     59                 --num[j];
     60                 LL tmp = Permutation(n - 1 - i);
     61 
     62                 if(tmp < x)
     63                 {
     64                     ++num[j];
     65                     x -= tmp;
     66                     continue;
     67                 }
     68 
     69                 ans[i] = j + 'a';
     70                 break;
     71             }
     72 }
     73 
     74 /*
     75 void dfs(int cur, int n, LL x)
     76 {
     77     if(n == 0)
     78         return;
     79 
     80     for(int i = 0; i < 26; ++ i)
     81         if(num[i])
     82         {
     83             --num[i];
     84             LL tmp = Permutation(n - 1);
     85 
     86             if(tmp < x)
     87             {
     88                 ++num[i];
     89                 x -= tmp;
     90                 continue;
     91             }
     92 
     93             ans[cur] = i + 'a';
     94             dfs(cur + 1, n - 1, x);
     95         }
     96 }*/
     97 
     98 int main()
     99 {
    100     int T;
    101     scanf("%d", &T);
    102     fact[0] = 1;
    103 
    104     for(int i = 1; i < 16; ++ i)
    105         fact[i] = fact[i - 1] * i;
    106 
    107     for(int tCase = 1; tCase <= T; ++ tCase)
    108     {
    109         scanf("%s%d", str, &n);
    110         printf("Case %d: ", tCase);
    111         LL MaxNumber = MaxPalindromic();
    112 
    113         if(MaxNumber < n)
    114             puts("XXX");
    115         else
    116         {
    117             //dfs(0, len, n);
    118             solve(n, len);
    119 
    120             for(int i = 0; i < len; ++ i)
    121                 putchar(ans[i]);
    122 
    123             if(OddChar != '#')
    124                 putchar(OddChar);
    125 
    126             for(int i = len - 1; i >= 0; -- i)
    127                 putchar(ans[i]);
    128 
    129             putchar('
    ');
    130         }
    131     }
    132 
    133     return 0;
    134 }
    View Code
  • 相关阅读:
    poj2478
    poj2376
    poj2192
    poj1062
    [HDOJ2639]Bone Collector II(第k优01背包)
    [HDOJ3466]Proud Merchants(贪心+01背包)
    [HDOJ5510]Bazinga(并查集)
    [POJ3264]Balanced Lineup(线段树,区间最值差)
    [HDOJ4325]Flowers(树状数组 离散化)
    [HDOJ5521]Meeting(最短路)
  • 原文地址:https://www.cnblogs.com/tank39/p/3911400.html
Copyright © 2020-2023  润新知