UVA 11027 - Palindromic Permutation

  题目意思为解码字符串,要输出第n个回文字符串,因为对称关系,前一半确定了,后一半也就跟着确定了,所以n其实就是前一半字符串的编码,还要减去1,直接解码出来再复制给后半即可

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4
  5 using namespace std;
  6
  7 typedef long long ll;
  8
  9 int T,a[26],st[26],cas=1,len;
 10 ll n;
 11 char s[50];
 12
 13 ll fa(int &x)//阶乘
 14 {
 15     ll res=1;
 16     for(int i=2;i<=x;i++)
 17         res*=i;
 18     return res;
 19 }
 20
 21 ll f(int*st)//种数
 22 {
 23     ll x=1,y=1;
 24     int sum=0;
 25     for(int i=0;i<26;i++)
 26     {
 27         if(st[i]>1) y*=fa(st[i]);
 28         sum+=st[i];
 29     }
 30     x=fa(sum);
 31     return x/y;
 32 }
 33
 34 ll code(char*s,int *st)//编码,这里没用到,开始理解错题意,以为是大于给出字符串的第n个回文字符串,打了一大堆才发现理解错题意了,main函数中的已删除,编码的就留着
 35 {
 36     ll x=0;
 37     for(int i=0;i<len>>1;i++)
 38     {
 39         int cnt=0;
 40         st[s[i]-‘a‘]--;
 41         for(int j=i+1;j<len>>1;j++) if(s[j]<s[i]) cnt++;
 42         x+=cnt*f(st);
 43     }
 44     return x;
 45 }
 46
 47 void decode(ll &goal,int*st)//解码
 48 {
 49     int l=len>>1;
 50     for(int i=0;i<l;i++)
 51     {
 52             ll x=0;
 53         for(int j=0;j<26;j++)
 54         {
 55             if(!st[j]) continue;
 56             st[j]--;
 57             ll y=f(st);
 58             x+=y;
 59             if(goal<x)//比如a开头的有6种,b开头的有3种,要找第八种,则应该是b开头的
 60             {
 61                 s[i]=j+‘a‘;
 62                 goal-=x-y;
 63                 break;
 64             }
 65             else st[j]++;
 66         }
 67     }
 68 }
 69
 70 int main()
 71 {
 72     scanf("%d",&T);
 73     while(T--)
 74     {
 75         scanf("%s%lld",s,&n);
 76         printf("Case %d: ",cas++);
 77         memset(a,0,sizeof(a));
 78         int i,x;
 79         len=strlen(s);
 80         for(i=0;i<len;i++)
 81             a[s[i]-‘a‘]++;
 82         i=0;
 83         if(len&1)
 84         {
 85             for(;i<26;i++)
 86             {
 87                 if(a[i]&1)
 88                 {
 89                     a[i]>>=1;
 90                     x=i;//x记下长度为奇数时中间那个
 91                     break;
 92                 }
 93                 a[i]>>=1;
 94             }
 95             i++;
 96         }
 97         for(;i<26;i++)
 98         {
 99             if(a[i]&1) break;
100             a[i]>>=1;
101         }
102         if(i<26)
103         {
104             puts("XXX");
105             continue;
106         }
107                 ll goal,all;//最大可能是(30/2)!,超出了int范围,要用ll
108         all=f(a);
109         goal=n-1;
110         if(goal>=all) strcpy(s,"XXX");
111         else
112                 {
113                         decode(goal,a);
114                         for(int i=0;i<len>>1;i++)
115                                 s[len-i-1]=s[i];
116                         if(len&1) s[len>>1]=x+‘a‘;
117                 }
118                 puts(s);
119     }
120     return 0;
121 }

时间: 2024-10-10 11:12:16

UVA 11027 - Palindromic Permutation的相关文章

UVA 11404 Palindromic Subsequence[DP LCS 打印]

UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求LCS,转移同时维护f[i][j].s为当前状态字典序最小最优解 f[n][n].s的前半部分一定是回文串的前半部分(想想就行了) 当s的长度为奇时要多输出一个(因为这样长度+1,并且字典序保证最小(如axyzb  bzyxa,就是axb)) // // main.cpp // uva11404 //

[题解]UVA11027 Palindromic Permutation

链接:http://vjudge.net/problem/viewProblem.action?id=19602 描述:给出一个字符串,求重新排列后第n个回文串,若没有则输出”XXX“. 思路:组合数问题. 首先考虑什么时候有回文串.很简单,数量为奇数的字母不超过1个.且这个字母只能是在字符串的中间. 然后我们会发现,回文串的字典序就是字串前半部分的字典序.问题就转化成求字典序第n的字符串.于是我们可以试着模拟一下这个过程.首先把字典序最小的字母放在第一个位置,然后计算出后面字母的排列数,即固定

LPS UVA 11404 Palindromic Subsequence

题目传送门 1 /* 2 LPS(Longest Palidromic Subsequence):最长回文子序列,和回文串不同,子序列是可以不连续的. 3 转化为LCS问题,将字符串逆序,然后和本串求LCS就是LPS的长度(为啥不就是LPS?),但是前一半是LPS的一半,可以补全 4 推荐->还有一种写法是用了LCS的思想,dp[i][j]表示i到j的最长回文串长度,状态转移方程: 5 1. dp[j][j+i-1] = dp[j+1][j+i-2] + 2; (str[j] == str[j+

【UVa】Palindromic Subsequence(dp+字典序)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=465&page=show_problem&problem=2399 最长的很简单,将串翻转过来后求两个串的lcs就是答案.. 主要是字典序那里... 还是开string来比较吧.. 注意最后输出方案时用前半段推出后半段.(因为可能lcs时会重合...) #include <cstdio> #include

6 UVA 10252 Common Permutation

求两个字符串的最长公共串. 即统计各字符出现的次数,按字母序枚举,输出该字符两个字符串中出现的较少次数. #include<cstdio> #include<cstring> int cnt1[50],cnt2[50]; char s1[1010],s2[1010]; int main() { int i,j,len1,len2; while(gets(s1)!=NULL) { gets(s2); len1=strlen(s1); len2=strlen(s2); memset(c

UVA 11404 Palindromic Subsequence

题解: 神一般的trick 首先求最长回文字符串的长度.只用反过来.转换为LCS问题就行 但是关键的要输出字典序最小的 所以在LCS的过程中.保存相应的字符串,并且保证字符串最小.这么求得的长度是对的.但是不一定是回文字符串 例如 bcbabccb bccbabcb ---> bcabc. 想了很久.可能是因为字典序的问题.当前面一半固定的时候,后面一半应该是前面一半的翻转过来,但是有可能出现和前面一半一样的情景.....(有毒) 具体修改.就是取前面一半即可 代码: #include<bit

UVA题目分类

题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics 10300 - Ecological Premium 458 - The Decoder 494 - Kindergarten Counting Game 414 - Machined Surfaces 490 - Rotating Sentences 445 - Marvelous Mazes

267. Palindrome Permutation II

Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form. For example: Given s = "aabb", return ["abba", "baab"]. Given s = "a

Palindrome Permutation II 解答

Question Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form. For example: Given s = "aabb", return ["abba", "baab"]. Given s