#47527: C++答案


yp11451058@yphs.tp.edu.tw (710-23沈庭維)

學校 : 臺北市私立延平高級中學
編號 : 312772
來源 : [203.72.178.1]
最後登入時間 :
2025-07-10 13:43:53

#include <iostream>
#include <string>
#include <vector>
using namespace std;

typedef long long ll;

ll comb[27][27]; // 組合數表 C(n, k)

// 預先計算組合數 C(n, k)
void precompute_combinations() {
    for (int n = 0; n <= 26; ++n) {
        comb[n][0] = 1;
        for (int k = 1; k <= n; ++k) {
            comb[n][k] = comb[n - 1][k - 1] + comb[n - 1][k];
        }
    }
}

// 判斷字串是否嚴格遞增字母序
bool is_strictly_increasing(const string &s) {
    for (int i = 1; i < (int)s.size(); ++i) {
        if (s[i] <= s[i - 1]) return false;
    }
    return true;
}

// 計算字串 s 在同長度字串中,比它字典序小的數量
ll count_lex_less(const string &s) {
    int n = s.size();
    ll result = 0;
    int prev_char = 0; // 字母序號起點,a=1

    for (int i = 0; i < n; ++i) {
        int cur_char = s[i] - 'a' + 1;
        // 從上一個字母序號+1開始,到當前字母序號-1之間的字母,嘗試放在第 i 個位置
        for (int ch = prev_char + 1; ch < cur_char; ++ch) {
            // 剩下位置為 n - i - 1,要從 ch+1 ~ 26 選剩下字母數
            int remain = 26 - ch;
            int need = n - i - 1;
            if (remain >= need)
                result += comb[remain][need];
        }
        prev_char = cur_char;
    }
    return result;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    precompute_combinations();

    while (true) {
        string word;
        cin >> word;
        if (word == "0") break;

        if (!is_strictly_increasing(word)) {
            cout << 0 << "\n";
            continue;
        }

        int length = word.size();

        // 計算比該長度小的所有字串數目
        ll rank = 0;
        for (int l = 1; l < length; ++l) {
            rank += comb[26][l];
        }

        // 計算同長度且字典序小於該字
        rank += count_lex_less(word);

        // 編碼從1開始,加1
        cout << rank + 1 << "\n";
    }

    return 0;
}