1. 程式人生 > >POJ - 1850 Code(排列組合)

POJ - 1850 Code(排列組合)

Transmitting and memorizing information is a task that requires different coding systems for the best use of the available space. A well known system is that one where a number is associated to a character sequence. It is considered that the words are made only of small characters of the English alphabet a,b,c, …, z (26 characters). From all these words we consider only those whose letters are in lexigraphical order (each character is smaller than the next character).

The coding system works like this:
• The words are arranged in the increasing order of their length.
• The words with the same length are arranged in lexicographical order (the order from the dictionary).
• We codify these words by their numbering, starting with a, as follows:
a - 1
b - 2

z - 26
ab - 27

az - 51
bc - 52

vwxyz - 83681

Specify for a given word if it can be codified according to this coding system. For the affirmative case specify its code.
Input
The only line contains a word. There are some constraints:
• The word is maximum 10 letters length
• The English alphabet has 26 characters.
Output
The output will contain the code of the given word, or 0 if the word can not be codified.
Sample Input


bf
Sample Output
55
題目連結
參考題解1
參考題解2
這個題目求這個字串的位序,其實就是求他前面的個數加一,並且輸入的字串都應該是嚴格遞增的序列。先求 len<x的字串數量,再求len==x,比當前字串小的數量,只要選出一定的字母,那麼他們的順序就一定確定下來了,接下來就是找排列數的問題了。首先對楊輝三角預處理了一下,後面就是做數學題了。

#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
LL inf = 15;
LL n, m;
char tm[15];
LL c[30][30];

//預處理工作,儲存楊輝三角所有值
void pre()
{
	 LL i, j;
	 for (i = 0; i <= 26; i++)
		 c[i][0] = 1;
	 for (i = 1; i <= 26; i++)
		 for(j = 1; j <= i; j++)
			 c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]);
}
//檢驗字元是否合法,要單調增
int check(char *s, int len)
{
    for (int i = 1; i < len; i++)
    {
        if (s[i] <= s[i - 1]) return 0;
    }
    return 1;
}

int main()
{
	pre();
    scanf("%s", tm);
    int len = strlen(tm);
    int ret = check(tm, len);
    if (!ret)
    {
        printf("0\n");
        return 0;
    }
    LL sum = 0, i, j;
    for (i = 1; i < len; i++)//累計所有長度小於len的字串個數
        sum += c[26][i];

    //接下來算長度等於len的字串個數
    if (tm[0] > 'a')
    {
        LL tmp = 0;
        for (i = 1; i <= tm[0] - 'a' - 1 + 1; i++) //tm[0]-'a'+1得到該字母對應數字,減一表示按照嚴格遞增
            tmp += c[26 - i][len - 1];
        sum += tmp;
    }

    for (i = 1; i < len; i++)
    {
        if (tm[i] - 1 - tm[i - 1] > 0)
        {
            LL tmp = 0;
            for (j = tm[i - 1] - 'a' + 1 + 1; j <= tm[i] - 'a' + 1 - 1; j++) //tm[i-1]-'a'+1得到該字母對應數字,加一表示按照嚴格遞增,不與i-1個字元重複,其他同理
                tmp += c[26 - j][len - i - 1];
            sum += tmp;
        }
    }
    printf("%lld\n", sum+1);
	return 0;
}