题意:
给出n和k,将1~n按字典序排序,问第k个是几
这道题限制蛮大, 不是时间超限就是内存超限,不能把1~n或者是1~k列出,按字典树列出也不可以,只能找规律做,上面这个代码是学长的找规律做的,下面那个代码是我用字典树做的,内存超限
这个代码很巧妙,我想这样做可是智商不够没有想出来
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string.h>
using namespace std;
int N = 100010;
int qianz(int n,int i) //以i为前缀的 小于N的数有多少个
{
int y = i + 1, num = 0;
while(i <= n)
{
num += min(y,n + 1) - i;
i *= 10, y *= 10;
}
return num;
}
int main()
{
int t, n, k,s;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
s = 1;
k--;
while(k)
{
int num = qianz(n, s);
if(num <= k)
{
k -= num;
s++;
}
else
{
k--;
s *= 10;
}
}
printf("%d\n",s);
}
}
用字典树做(超内存)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
using namespace std;
int n,k;
int ans[25],an;
int sum[10];
struct node
{
bool flag;
node *next[11];
// int sum;
}*root;
node *build()
{
node *p = (node *)malloc(sizeof(node));
for(int i = 0; i < 10; i ++)
p -> next[i] = NULL;
p -> flag = false;
//p->sum=0;
return p;
}
void save(char *s)
{
node *p;
p = root;
int len = strlen(s);
for(int i = 0; i < len; i ++)
{
if(p -> next[s[i] - '0'] == NULL)
p -> next[s[i] - '0'] = build();
if(p==root)
sum[s[i]-'0']++;
p = p -> next[s[i] - '0'];
}
p -> flag = true;
}
int kk;
void query(node *p)
{
if(kk==k)
return;
for(int i = 0; i <= 9; i ++)
{
if(p -> next[i] != NULL)
{
//printf("(%d %d) ",i,kk);
if(p->next[i]->flag==true)
kk++;
query(p->next[i]);
if(kk==k)
{
ans[an++]=i;
return;
}
}
}
return;
}
void clear(node *p)
{
for(int i = 0; i < 10; i ++)
{
if(p -> next[i] != NULL)
clear(p -> next[i]);
p -> next[i] = NULL;
}
return;
}
int main()
{
char str[25];
int s[25];
int t;
cin>>t;
while(t--)
{
root = build();
scanf("%d %d",&n,&k);
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
int num=i,f=0;
while(num!=0)
{
s[f++]=num%10;
num=num/10;
}
for(int j=f-1;j>=0;j--)
{
str[f-1-j]=s[j]+'0';
//printf("%c",str[f-1-j]);
}
save(str);
//cout<<endl;
}
kk=0;
node *p;
p = root;
int i=1;
for(i=1;i<=9;i++)
{
if(p->next[i]==NULL)
continue;
if(sum[i]<k)
{
k=k-sum[i];
}
else
break;
}
an=0;
memset(ans,0,sizeof(ans));
//printf("i=%d\n",i);
k--;
query(p->next[i]);
ans[an++]=i;
for(int i=an-1;i>=0;i--)
printf("%d",ans[i]);
cout<<endl;
clear(p);
}
return 0;
}
/************************************
这几天可能太紧张了吧,昨晚梦到了高考,不是回到了高三,而是现在紧张兮兮的想补学点什么,觉得没有学够。讲真我高三的时候都没有这样的心态的