SERC2013 B Nested Palindromes

http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11442&courseid=0


B:   Nested Palindromes
Palindromes  are  numbers  that  read  the  same  forwards  and  backwards.  Your  friend 
Percy recently became interested in  a special kind of palindrome that he calls a  Nested 
Palindrome. A Nested Palindrome meets three conditions:
  The number is a palindrome. 
  Split the number in the middle. The first half of the digits of the number is also a 
Nested Palindrome. If  the  number  has  an odd  number  of  digits, don’t  consider 
the middle digit as part of the first half.
  No two adjacent digits are the same.
Percy  says that he  has written a  Nested Palindrome  with no leading zeros on a slip of 
paper.  Next,  Percy  says  that  he  has  erased  some  of  the  digits  in  the  number  and 
replaced  those  digits  with  question  marks.  He  asks  you  to  think  about  all  possible 
numbers,  in  increasing  order,  that  can  fill  those  digits  and  could  possibly  form  the 
number Percy wrote. Of course, Percy may not be telling the truth about having written 
a Nested Palindrome in the first place.
Percy tells you that the number he wrote is the  kth number of this potentially large list. 
Your task is to find that kth number.
Input
There will be several test cases in the input. Each test case will consist of two lines. The 
first line will contain an integer k (1≤k≤10
18
), which is the position in the ordered list you 
must  find.  The  second  line  contains  a  string  of  length  1  to  10,000,  consisting  only  of 
digits (‘0’ to ‘9’) and question marks (‘?’). Input is terminated by a line with a single 0.
Output
For  each  test  case,  output  the  Nested  Palindrome  that  Percy  is  looking  for.  If  that 
number  does  not  exist,  or  if  the  string  cannot  form  a  Nested  Palindrome,  output  -1. 
Output no spaces, and do not separate answers with blank lines. 
2013 ACM ICPC Southeast USA Regional Programming Contest
Page 4 of 16    2 November, 2013
Sample Input
1
1?1
1
?3?
1
?1?
55
???
55
1?1
3
0?0
0

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn=11000;

int lenth[20],len,pos;
int num[20],arr[20],NB[20],wei;
bool flag,vis[20];
char str[maxn];

long long int pow9[20],cut,kth;

void POW9()
{
    pow9[0]=1;
    for(int i=1;i<=14;i++) pow9[i]=pow9[i-1]*9;
}

void dfs(int n,int limit)
{
    if(flag) return ;
    if(n==wei)
    {
        cut--;
        if(cut==0LL)
        {
            flag=true;
            for(int i=0;i<wei;i++)
            {
                NB[i]=arr[i];
            }
        }
        return ;
    }

    for(int i=0;i<=9;i++)
    {
        if(i==limit) continue;
        if(pow9[wei-n-1]<cut)
        {
            cut-=pow9[wei-n-1];
            continue;
        }
        arr[n]=i;
        dfs(n+1,limit);
    }
}

void init()
{
    POW9();
    for(int i=0;i<15;i++) lenth[i]=(1<<i)-1;
}

void PT(int n)
{
    if(n==-1) return ;
    PT(n-1);
    printf("%d",num[n]);
    PT(n-1);
}

int main()
{
    init();
while(scanf("%I64d",&kth)!=EOF&&kth)
{
    scanf("%s",str);
    len=strlen(str);  pos=-1;
    memset(num,-1,sizeof(num));
    memset(vis,false,sizeof(vis));
    for(int i=1;i<15;i++) { if(lenth[i]==len) pos=i; }
    if(pos==-1)
    {
        puts("-1"); continue;
    }
    int nev=0;
    for(int i=0;i<pos;i++)
    {
        if(str[(1<<i)-1]!='?')
        {
            num[i]=str[(1<<i)-1]-'0';
            vis[num[i]]=true;
        }
        else nev++;
    }
    if(num[0]==0)
    {
         puts("-1"); continue;
    }
    long long int maxleve=pow9[nev];

    if(maxleve<kth)
    {
        puts("-1"); continue;
    }

    flag=false;
    if(num[0]==-1) ///a的值是未知,a不能是0,a不能是其他已知的数  其他数不能是a有9种选择
    {
        maxleve/=9;
        int ath=1,a=-1;
        while(kth>maxleve) ath++,kth-=maxleve;
        for(int i=1;i<=9;i++)
        {
            if(vis[i]==0)
            {
                ath--;
                if(ath==0)
                {
                    a=i; break;
                }
            }
        }
        if(a==-1)
        {
            puts("-1"); continue;
        }
        cut=kth;num[0]=a;wei=nev-1;
        dfs(0,num[0]);
    }
    else ///a的值已知,其他数不能是a有9种选择
    {
        cut=kth;wei=nev;
        dfs(0,num[0]);
    }
    if(flag==false)
    {
        puts("-1"); continue;
    }

    int st=0;
    for(int i=0;i<pos;i++)
    {
        if(num[i]==-1)
        {
            num[i]=NB[st++];
        }
    }

    PT(pos-1); putchar(10);
}
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值