# 第一问

j一定小于等于i/2。

f[i]=2ii2j=1f[j]2i2j$f[i]=2^i-\sum_{j=1}^{\frac{i}{2}}f[j]*2^{i-2*j}$

# 第二问

j与上一问的意义一致。

1、i<=len$i<=len$

2、len<=j$len<=j$

3、j<len<=ij$j

4、len>ij$len>i-j$

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll maxn=80+10;
ll ans[maxn],next[maxn],f[maxn],two[maxn];
ll i,j,k,l,t,n,m,ca,len,last;
ll pd(ll x){
ll i;
fo(i,1,x)
if (ans[i]!=ans[len-x+i]) return 0;
return 1;
}
ll solve(){
ll i,j,t;
fo(i,1,n){
if (i<=len){
if (!next[i]) f[i]=1;else f[i]=0;
continue;
}
f[i]=two[i-len];
fo(j,1,i/2){
if (len<=j) t=two[i-2*j];
else if (j<len&&len<=i-j) t=two[i-2*j-(len-j)];
else t=pd(len-(i-j));
f[i]-=f[j]*t;
}
}
return f[n];
}
void insert(ll x){
ans[++len]=x;
if (len==1) return;
while (last&&ans[last+1]!=ans[len]) last=next[last];
if (ans[last+1]==ans[len]) last++;
next[len]=last;
}
int main(){
freopen("word.in","r",stdin);freopen("word.out","w",stdout);
two[0]=1;
fo(i,1,64) two[i]=two[i-1]*2;
scanf("%lld",&ca);
while (ca--){
scanf("%lld%lld",&n,&m);
len=last=0;
printf("%lld\n",solve());
fo(i,1,n){
k=last;
insert(0);
t=solve();
if (t<m){
m-=t;
last=k;
len--;
insert(1);
}
}
fo(i,1,n) printf("%c",ans[i]+'a');
printf("\n");
}
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120