https://codeforces.com/problemset/problem/1328/B
思路:两个b的分布是有规律的,我们可以找到规律然后直接输出,首先,我们将 n*(n-1)/2 个字符串分成 n-1个区间,每个区间内有的字符串为 i 个 (1<= i <=n-1),第一个b分布的位置为 i+1,第二个b根据所求的 k 在这个区间内是第几个就在第几个
例如:n = 5,k = 8;总共可以分为四个区间,每个区间依次有的字符串为 1 2 3 4,
第四个区间的字符串依次为:
- baaab
- baaba
- babaa
- bbaaa
k=8在区间 [7, 10 ]内排第二个,所以第一个b的位置为 4+1=5,第二个b的位置为2;
那么,根据以上规律,我们先预处理一下每个区间的左端点,然后再判断k是在第几个区间内和在这个区间内排第几位
以下是代码实现:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll num[N];
void solved()
{
ll n,k;
cin>>n>>k;
ll l=1,r=1,flag=(n*(n-1))/2;
int cnt=2;
num[1]=1;
while(r<flag)
{
l=r+1,r=r+cnt;
num[cnt]=l;
cnt++;
}
num[cnt]=r;
ll x=1,cnt1=2;
for(ll i=1;i<=cnt;i++)//求k所在区间的位置
{
if(num[i]>k||(num[i]==k&&i==cnt))
{
cnt1=i-1;
break;
}
if(num[i]==k)
{
cnt1=i;
break;
}
}
ll cnt2=k-num[cnt1]+1;//k在这个区间内排第几位
//cout<<cnt1<<" "<<cnt2<<" "<<num[cnt1]<<endl;
for(ll i=n;i>=1;i--)
{
if(i==cnt1+1||i==cnt2) cout<<"b";
else cout<<"a";
}
cout<<endl;
return ;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin>>t;
while(t--)
{
solved();
}
return 0;
}