SIGMA={a,b,c} SIGMA* is based on SIGMA with these rules:
1. SIGMA ⊆ SIGMA*
2. if s1∈SIGMA*, s2∈ SIGMA*, then s1s2∈SIGMA*
3. Any element of SIGMA* can be formed within finite application of rule 1) 2)
The elements in SIGMA* are firstly ordered by length (short to long), and alphabetically ordered when of the same length.
Design an algorithm to solve (empty string is ordered 0):
1) given a string alpha, find the sequence number
2) given a sequence number, find alpha
给定seq求alpha相对比较麻烦:
离散数学课上的一个思考题,把a b 和c理解为数字0 1 和2,SIGMA*集合实际上是一个允许有前0的三进制无符号整数有序集合,其标号从1开始,长度l的最小数字L_l=(3^0+3^1+...+3^(l-1)),任意给定序号seq求长度len,可以令L_l大于seq解出长度len等于log_3(2*seq+1)的整数部分。求出长度后将seq与在这个长度下的最小数的序号相减得到leap,接下来就是从大到小每一位上把leap除以这个位对于的3的那个次方,得到整数部分就是这个位与a的差距了,然后将leap减去用这个位抵消的部分,循环直到个位被完成。
给定alpha求seq很简单,按位(a是1,b是2,c是3)乘上对应的3的那个次方,加起来就行了
这个题目某种程度上揭露了一些允许有前0的集合以及不允许有前0的集合的区别:
不允许前0的集合有一特点,那就是如果规定'1'是第1个元素,那么按照长度+字典序排序(正如本题叙述的),每个数字的大小也正好等于其序号。这里数字的大小指的是:这个字符串代表的数字,其各位上的单个数乘以这个位在进制内对应的幂再求和,例如十进制的123等于1*100+2*10+3*1。这对于任意k进制都成立,用等比级数的部分和公式很简单可以证明(规定长度为0的字符串只有1个'0',长度1有(k-1)个,长度i的有(k-1)*k^(i-1)个,因为可以增加(k-1)个数字在最前端);在这样的集合中给定一个字符串的序号就知道其大小,我要得到其长度只直接对序号取对数再取整就行了。
但是由于允许前0的存在,同样的数字大小计算方法得到的就不是其序号了,如果想要达到这个目的,就需要改变计算方法。如本题所述规定'0'是第1个元素的话,每个数字的'大小'应当其各位上的单个数的序号乘以这个位在进制内对应的幂再求和。例如三进制的012,0的序号为1,1为2,2为3,012=1*9+2*3+3*1。对应着幂依旧成立是因为这位后面的位的组合方法依旧是那么多,但是由于0开始就表示了有1个这个位,所以要改成序号。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
using namespace std;
string alpha;
int seq=0;
void findseq()
{
int len = alpha.length();
for (int i = 0; i < len; i++)
seq += (alpha[i]-96) * pow(3, len - i - 1);
}
void findalpha()
{
if (seq == 0) return;
int len = log(2*seq+1)/log(3);
int leap = seq-int((pow(3,len)-3)/2)-1;
for (int i = 0; i < len; i++)
{
int bitleap = leap / pow(3,len-i-1);
alpha += 'a' + bitleap;
leap -= pow(3, len - i - 1)*bitleap;
}
}
void solveseq(string tmp)
{
for (int i = 0; i < tmp.length(); i++)
seq += pow(10, tmp.length() - i - 1)*(tmp[i] - '0');
findalpha();
cout << alpha << endl;
}
void solvealpha(string tmp)
{
alpha = tmp;
findseq();
cout << seq << endl;
}
int main()
{
string tmp;
cin >> tmp;
if (tmp[0] >= 'a')
solvealpha(tmp);
else
solveseq(tmp);
return 0;
}