Official

C - abc285_brutmhyhiizp Editorial by physics0523


まず、 \(k\) 文字の ID は \(26^k\) 通りあることがわかります。
また、 \(k\) 文字以下の ID は全部で \(26^1+26^2+\dots+26^k\) 通りであることもわかります。

では、 \(l\) 文字の ID である \(S\) が何問目かを実際に求めていきましょう。
実は、以下のように計算することが可能です。

最初、答えを \(26^1 + 26^2 + \dots + 26^{l-1}\) で初期化する。

  • \(i = 1,2,\dots,l\) について以下を繰り返す。
    • \(S\)\(i\) 文字目がアルファベット大文字辞書順で \(x\) 番目であった場合、答えに \((x-1) \times 26^{l-i}\) を加算する。

最後に答えに \(1\) を加算して出力する。 (この加算によって \(0\) 始まりの番号付け(0-indexed) から \(1\) 始まりの番号付け(1-indexed) に切り替えられます。)


この解法にはいくつかの解釈があります。
例えば ID が QWERTY であるとき、答えを以下のように数えていくことができます。

順を追って数え上げる
  • \(5\) 文字以下の ID は全部で \(26^1 + 26^2 + \dots + 26^5\) 通り
  • \(6\) 文字で A から始まる ID A?????\(26^5\) 通り
  • \(6\) 文字で B から始まる ID B?????\(26^5\) 通り
  • \(\vdots\)
  • \(6\) 文字で P から始まる ID P?????\(26^5\) 通り
  • \(6\) 文字で QA から始まる ID QA????\(26^4\) 通り
  • \(6\) 文字で QB から始まる ID QB????\(26^4\) 通り
  • \(\vdots\)
  • \(6\) 文字で QWA から始まる ID QWA???\(26^3\) 通り
  • \(\vdots\)
  • \(6\) 文字で QWEA から始まる ID QWEA??\(26^2\) 通り
  • \(\vdots\)
  • \(6\) 文字で QWERA から始まる ID QWERA?\(26^1\) 通り
  • \(\vdots\)
  • \(6\) 文字で QWERTA から始まる ID QWERTA\(26^0\) 通り
  • \(\vdots\)
\(26\) 進数として解釈する
  • \(5\) 文字以下の ID は全部で \(26^1 + 26^2 + \dots + 26^5\) 通り

というところは同じですが、 QWERTY\(26\) 進数として解釈します。 AAAAAA\(0\) 番目、 AAAAAB\(1\) 番目、 \(\dots\)AAAAAZ\(25\) 番目、 AAAABA\(26\) 番目、 \(\dots\) というように番号を付けた際、各英大文字を \(0,1,\dots,25\) と対応付けることによって、文字列を \(26\) 進数と同様に取り扱うことができます。なので、入力を \(26\) 進数と解釈し \(10\) 進数に直して出力するようなことを行えばよいです。


実装例 (C++) :

#include<bits/stdc++.h>

using namespace std;

int main(){
  string s;
  cin >> s;
  int l=s.size();
  long long res=0,add=26;
  for(int i=1;i<=l-1;i++){res+=add;add*=26;}
  long long num=0;
  for(int i=0;i<l;i++){
    num*=26;
    num+=(s[i]-'A');
  }
  cout << res+num+1 << "\n";
  return 0;
}

posted:
last update: