Problem E
Arranging Cards
Input: Standard Input
Output: Standard Output
Given n (n <= 50) different cards, you're going to arrange them in a sequence so that adjacent cards always have different ranks.
Each card is represented by two characters: its rank (2~9,T for ten,J for Jack,Q for Queen,K for King,A for Ace) and suite (S for Spade,C for Club,H for Heart,D for Diamond). The whole sequence is represented by the concatenation of all the cards. For example, 6H7DJDKC is a valid sequence, but 6H7D7SKC is not, because there are two adjacent cards 7D and 7S with the same rank.
Given a positive integer k (1 ≤ k ≤ 1018), find the lexicographically k-th smallest sequence.
Input
The input contains at most 1000 test cases. Each case begins with two integers n and k in the first line. The second line contains n cards separated by a single space. The case with n = 0 indicates the end of the input and should not be processed.
Output
For each case, print the case number and the answer. If there is no such sequence, print "Not found" (without quotes). Insert a single space between each two adjacent cards to make it look better.
Sample Input
6 1 2S 3S 3C 4S 4C 4D 6 120 2S 3S 3C 4S 4C 4D 6 121 2S 3S 3C 4S 4C 4D 16 654321234567 2S 3S 4S 5S 2C 3C 4C 5C 2D 3D 4D 5D 2H 3H 4H 5H 0 0 |
Output for Sample Input
Case 1: 2S 4C 3C 4D 3S 4S Case 2: 4S 3S 4D 3C 4C 2S Case 3: Not found Case 4: 5D 4S 2D 5H 3S 4H 5S 2H 3D 2C 5C 4D 2S 3C 4C 3H |
Problemsetter: Rujia Liu
Special thanks: Dong Zhou
题意:有n张牌,各个牌是不一样的,即使他们有一样的rank和suit也是不一样的。 现在要将他们排成一行,并且相邻的牌的rank不一样。 求字典序是第k小的情况。
思路:算是这题的加强版.....http://www.lydsy.com/JudgeOnline/problem.php?id=1079
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <map>
#include <set>
#include <stdio.h>
#include <cmath>
#include <cassert>
#include <math.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define LL unsigned long long
#define eps 1e-9
#define mp make_pair
using namespace std;
const LL maxk = 1e18;
struct State
{
short pre;
short a[51];
bool operator < (const State & st) const
{
if (pre != st.pre) return pre < st.pre;
rep(i,0,51)
if (a[i] != st.a[i]) return a[i] < st.a[i];
return false;
}
bool operator == (const State & st) const
{
if (pre != st.pre) return false;
rep(i,0,51) if (a[i] != st.a[i]) return false;
return true;
}
};
const int maxn = 50+5;
int n;
long long K;
map<State,LL> dp;
int num[256],sum[maxn];
pair<char,char> card[maxn];
void input()
{
char s[10];
rep(i,0,n) {
scanf("%s",s);
card[i] = mp(s[0],s[1]);
}
sort(card,card+n);
}
int ans[maxn];
bool vis[maxn];
LL add(LL a,LL b)
{
if (a >= maxk || b >= maxk
|| a + b >= maxk) return maxk;
return a + b;
}
LL mul(LL a,LL b)
{
if (a > b) swap(a,b);
if (b >= maxk) return maxk;
if (a > maxk / b) return maxk;
return a * b;
}
LL dfs(State st)
{
map<State,LL>::iterator it;
it = dp.find(st);
if (it != dp.end()) return it->second;
LL & t = dp[st];
int n = 0,maxi = 0;
rep(i,0,51) {
n += st.a[i] * i;
if (st.a[i] > 0) maxi = i;
}
if (n == 0) return t = 1;
if (maxi + maxi - 1 > n) return t = 0;
int pre = st.pre;
rep(i,1,51) if (st.a[i]) {
--st.a[i];
if (i - 1 > 0) ++st.a[i-1];
st.pre = i;
t = add(t,dfs(st) * (st.a[i] + 1 - (pre == i+1)));
++st.a[i];
if (i - 1 > 0) --st.a[i-1];
if (t >= maxk) break;
}
return t;
}
LL A[maxn];
void solve()
{
clr(num,0); clr(sum,0);
rep(i,0,n) {
int x = ++num[card[i].first];
++sum[x]; --sum[x-1];
}
State start; clr(start.a,0);
rep(i,1,n+1) {
start.a[i] = sum[i];
start.pre = maxn*2;
}
clr(vis,0);
bool no_ans = false;
rep(i,0,n) {
int j = 0;
for(; j < n; ++j) if (!vis[j]) {
if (i > 0 && card[ans[i-1]].first == card[j].first) continue;
int x = --num[card[j].first];
vis[j] = true;
if (x > 0) ++start.a[x];
--start.a[x+1];
start.pre = x+1;
//++sum[x]; --sum[x+1];
LL t = dfs(start);
LL a = 1;
rep(k,2,n+1) {
rep(w,0,start.a[k]) {
a = mul(a,A[k]);
if (a >= K) break;
}
if (a >= K) break;
}
t = mul(t,a);
if (t >= K) break;
vis[j] = false;
K -= t;
if (x > 0) --start.a[x];
++start.a[x+1];
++num[card[j].first];
}
if (j >= n) {
no_ans = true;
break;
}
ans[i] = j;
}
if (no_ans || K != 1) puts("Not found");
else {
rep(i,0,n) {
char x = card[ans[i]].first;
char y = card[ans[i]].second;
printf("%c%c",x,y);
if (i != n-1) printf(" ");
}
puts("");
}
}
int main()
{
#ifdef ACM
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif // ACM
int cas = 0;
A[0] = 1;
rep(i,1,maxn) A[i] = mul(A[i-1],i);
while (scanf("%d",&n)==1) {
scanf("%lld",&K);
if (n == 0) break;
input();
++cas;
printf("Case %d: ",cas);
solve();
}
}