yukicoder 254 文字列の構成
問題
方針
ababab...
と繰り返す長さ $n$ の文字列に含まれる回文の数を $f(n)$ とおく.
$n$ が偶数のときは
a
,b
のパターンが $n$ 個aba
,bab
のパターンが $n-2$ 個ababa
,babab
のパターンが $n-4$ 個- …
となるので,合わせて $C(n/2,2) \times 2$ 個の回文が含まれる. ここで $C(i,j)$ は組み合わせ係数.
$n$ が奇数のときは,末尾の文字を使わないとき再帰的に $f(n-1)$ 個, 使うとき $(n+1)/2$ 個作れる.あわせて $f(n-1)+(n+1)/2$ 個である.
$f(k) \leq N$ となる最大の $k$ を求め,$N$ から引くということを,$N=0$ となるまで繰り返す.
毎回の ababa...
を答えの末尾に足していく.ループのたびに cdcdc...
, efefe...
と変えていき,
異なる区間をまたぐような回文ができないようにする.
実装
int g(int n){
return (1+n)*n/2;
}
int f(int n){
if(n&1) return (n+1)/2 + f(n-1);
else return g(n/2)*2;
}
int main(){
ll n;
cin >> n;
ll rem = n, step = 0;
string ans;
while(rem){
ll l = 0, r = 100010;
while(l+1 < r){
ll m = (l+r)/2;
ll x = f(m);
if(x <= rem) l = m;
else r = m;
rep(i,1000000);
}
rep(i,l) ans += char('a'+step*2+i%2);
step++;
rem -= f(l);
}
cout << ans << endl;
}