1. 程式人生 > 其它 >洛谷P1246 編碼 (題目 + 詳細註釋 + 程式碼)

洛谷P1246 編碼 (題目 + 詳細註釋 + 程式碼)

技術標籤:洛谷遞迴字串模擬組合數

題目傳送門

題目描述

編碼工作常被運用於密文或壓縮傳輸。這裡我們用一種最簡單的編碼方式進行編碼:把一些有規律的單詞編成數宇。

字母表中共有26個字母{a,b,…,z},這些特殊的單詞長度不超過6且字母按升序排列。把所有這樣的單詞放在一起,按字典順序排列,一個單詞的編碼就對應著它在字典中的位置。

例如:

a→1 b→2 z→26 ab→27 ac→28

你的任務就是對於所給的單詞,求出它的編碼。

輸入格式

僅一行,被編碼的單詞。

輸出格式

僅一行,對應的編碼。如果單詞不在字母表中,輸出0。

輸入輸出樣例

輸入

ab

輸出

27

解析: 假設待處理的字串 s = cs'(其中c為第一個字母, 令 c - 'a'+ 1 = t,s'為除去第一個字母剩下的字串)。那麼我們就可以 f[s] =\sum i * C (26 - i, len(s'))

+ f[s'] (其中 i 從 1 ~ t);因為s'的長度比s的長度少一,因此不斷遞迴下去,當字串長度為1時即可停止( f[c] = c - 'a' + 1)

程式碼:(遞迴)

#include<bits/stdc++.h> 
using namespace std;


//計算組合數
int C(int n, int m){
	int ans = 1;
	for(int i = 1; i <= m; i++){
		ans *= (n - m + i);
		ans /= i; 
	}
	return ans;
}

int solve(string s){
	int len = s.size();

    //字串首位
	int t = s[0] - 'a' + 1;
    //剩下的字串
	string ss = s.substr(1, len - 1);
    
    //長度為1,直接可得到答案
	if(len == 1) return t;
	
    //求和
	int sum = 0;
	for(int i = 1; i <= t; i++) sum += C(26 - i, len - 1);
    
    //遞迴處理
	return sum + solve(s.substr(1, len - 1));
}

int main(){
	string s;
	cin >> s;
	
	bool flag = true;

    //判斷字串是否符合題意
	for(int i = 0; i < s.size() - 1; i++)
		if(s[i] >= s[i + 1] || s[i] < 'a' || s[i] > 'z'){
			flag = false;
			break;
		}
	
	if(!flag) puts("0");
	else cout << solve(s) << endl;
	
	return 0;
}