K-th Beautiful String(CodeForces - 1328B )

B. K-th Beautiful String
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
For the given integer n (n>2) let’s write down all the strings of length n which contain n−2 letters ‘a’ and two letters ‘b’ in lexicographical (alphabetical) order.

Recall that the string s of length n is lexicographically less than string t of length n, if there exists such i (1≤i≤n), that si<ti, and for any j (1≤j<i) sj=tj. The lexicographic comparison of strings is implemented by the operator < in modern programming languages.

For example, if n=5 the strings are (the order does matter):

aaabb
aabab
aabba
abaab
ababa
abbaa
baaab
baaba
babaa
bbaaa
It is easy to show that such a list of strings will contain exactly n⋅(n−1)2 strings.

You are given n (n>2) and k (1≤k≤n⋅(n−1)2). Print the k-th string from the list.
The input contains one or more test cases.

The first line contains one integer t (1≤t≤104) — the number of test cases in the test. Then t test cases follow.

Each test case is written on the the separate line containing two integers n and k (3≤n≤105,1≤k≤min(2⋅109,n⋅(n−1)2).

The sum of values n over all test cases in the test doesn’t exceed 105.
For each test case print the k-th string from the list of all described above strings of length n. Strings in the list are sorted lexicographically (alphabetically).
Input
7
5 1
5 2
5 8
5 10
3 1
3 2
20 100
Output
aaabb
aabab
baaba
bbaaa
abb
bab
aaaaabaaaaabaaaaaaaa
题意:长度为n的字符串,其中由2个b,和n-2个a组成,按照顺序可以有[n*(n-1)]/2个排序,他们是按照一定顺序进行排序的,输出第k个字符串
思路:我刚开始看它字符串的规律是按照字典序的方法排序的,所以我最先使用了优先队列的办法,但是被T了,因为2⋅109太大了,之后借鉴一个大佬的,找规律,哎,思维还是太菜了,先确定倒数第二个b的位置,再去确定倒数第一个b的位置,
倒数第二个b的位置你倒着看就是从倒数第二个开始,后面到结尾有几个位置就有几种情况,把情况算成前缀和,来判断k值属于哪个区间中,然后确定了倒数第二个b的位置,再去确定倒数第一个b的位置
aaabb sum[2]=1;k=4;

aabab sum[3]=1+2=3
aabba

abaab sum[4]=3+3=6 break; j=i;k=k-sum[j-1]
ababa 4-sum[3]=4-3=1
abbaa s[n-j+1]=s[2] s[n-k+1]]=s[5]

baaab sum[5]=6+4
baaba
babaa
bbaaa

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e5+9;
ll sum[N];
char ch[N];
int main ()
{
    int n,k,t;
    scanf("%d",&t);
    for(int i=2;i<=100009;i++){
            sum[i]=sum[i-1]+i-1;//前缀和数组,因为是倒数第2个b是从倒数第二位开始算的,
            //所以,sum[i]就代表倒数第2个b是倒数第几个
            //sum[i-1]+i-1,因为每加一次就加i-1个,因为i是从2开始的,而第一种情况只有1种
    }
    for(int g=1;g<=t;g++){
        int j;
        scanf("%d %d",&n,&k);
        for(int i=2;i<=n;i++){
            if(sum[i]>=k){
                j=i;//如果前缀和数组大于等于了k,就代表在当前这个区间中
                break;
            }
        }
        k=k-sum[j-1];//k要减去之前的数量,来确定倒数第一个b所在的位置
        for(int i=1;i<=n;i++){
            ch[i]='a';
        }
        ch[n-j+1]='b';//倒数第二个b,是倒数第几个
        ch[n-k+1]='b';//倒数第一个b,是倒数第几个
        for(int i=1;i<=n;i++){
            printf("%c",ch[i]);//输出就行
        }
        cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值