uva 11027(数论)

来源:互联网 发布:sqlserver分页查询 编辑:程序博客网 时间:2024/06/07 04:06

题意:给一个字符串,把它的所有回文串按字典序排序,然后给了个n,要求输出第n个回文串是什么,如果没有就输出XXX。

题解:首先判断是否存在第n个回文串,用一个数组f[i]表示A(i),那么一个字符串的排列方式就有A(len) / A(i),其中len是字符串长度,i是指第i个字符的个数,然后先将字典序最小的字母放到两端,然后判断此时剩下的字符串有x种排法,如果x < n说明第一位不是字典序最小的,那么n -= x,否则就让字典序最小的字母放入结果串内,让剩下的字符串以此类推,直到结果串长度达到初始串的一半。


#include <stdio.h>#include <string.h>using namespace std;const int N = 40;char str[N], ans[N];int n, m[N];long long f[N];void init() {f[0] = 1;for (int i = 1; i <= 16; i++)f[i] = f[i - 1] * i;}long long get_num(int x) {long long sum = 1;for (int i = 0; i < 26; i++)sum *= f[m[i]];return f[x] / sum;}int main() {init();int t, cas = 1;scanf("%d", &t);while (t--) {scanf("%s%d", str, &n);printf("Case %d: ", cas++);memset(m, 0, sizeof(m));int len = strlen(str);for (int i = 0; i < len; i++)m[str[i] - 'a']++;int flag = 0, cnt = 0;char cc;for (int i = 0; i <= 25; i++) {if (m[i] % 2) {flag++;cc = i + 'a';}m[i] /= 2;cnt += m[i];}if (flag > 1 || get_num(cnt) < n) {printf("XXX\n");continue;}int res = 0;while (res != cnt) {for (int i = 0; i < 26; i++) {if (m[i]) {m[i]--;long long temp = get_num(cnt - res - 1);m[i]++;if (n <= temp) {ans[res++] = 'a' + i;m[i]--;break;}elsen -= temp;}}}for (int i = 0; i < res; i++)printf("%c", ans[i]);if (flag)printf("%c", cc);for (int i = res - 1; i >= 0; i--)printf("%c", ans[i]);printf("\n");}return 0;}

0 0
原创粉丝点击