<水一发>今天做的一道蓝桥杯的题目

来源:互联网 发布:中日互译软件 编辑:程序博客网 时间:2024/05/18 21:43
如果用a b c d这4个字母组成一个串,有4!=24种,如果把它们排个序,每个串都对应一个序号: 
  abcd  0 
  abdc  1 
  acbd  2 
  acdb  3 
  adbc  4 
  adcb  5 
  bacd  6 
  badc  7 
  bcad  8 
  bcda  9 
  bdac  10 
  bdca  11 
  cabd  12 
  cadb  13 
  cbad  14 
  cbda  15 
  cdab  16 
  cdba  17 
  ... 
    现在有不多于10个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗? 
【输入格式】 
一行,一个串。 
【输出格式】 
一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是0。 
例如: 
输入: 
bdca 
程序应该输出: 
11 
再例如: 
输入: 
cedab 
程序应该输出: 
70 
资源约定: 
峰值内存消耗 < 256M 

CPU消耗  < 1000ms 

课上花了10多分钟中找规律……

这个序列有个规律,就是每个位置上每个字母开头的可能性一样多
abcd序列中a开头的情况是四分之一,a之后b的可能性三分之一,ab之后从的可能性是二分之一……以此类推
d开头的时候序列号最少是18,dc开头的时候序列号最少是22……
需要注意的是第一个字母之后的判断
开头是a时,b排在bcd的第一个
但开头是c或者是d时,b排在a之后,第二个
这之间应该会有几个序号的差距


当b之前有a(ascII码比b小)时,后期排序中b排在第一位,较之正常的排序(第二位)高出一位
当d之前有abc(ascII码比d小)时,后期排序中d排在第一位,较之正常的排序(第四位)高出三位

下面上代码:

#include<iostream>
using namespace std;
short bol(char num[],short j)
{
short sum=num[j]-'a';
for(short i=0;i<j;i++)
{
if(num[i]<num[j])
sum--;
}
return sum;
}
int main()
{
char num[11]={' '};
long sum=1;
//给num赋值
cin.getline(num,11);
short i=0;
//计算总共会有多少种情况
for(;num[i];i++)
sum*=i+1;
long sum2=0;
for(short j=0;num[j]&&i!=0;j++)
{
//i--用来从四分之一到三分之一……的一个过渡
//sum每次都要减小,用以下次计算
//bol()函数用来做上方的那两行(ascII码)判断,确定当前num[j]的位数
sum2+=(sum/=i--)*(bol(num,j));
}
cout<<sum2<<endl;
return 0;
}

0 0