康拓展开&&逆康拓展开

举报
Linux猿 发表于 2021/08/04 23:15:51 2021/08/04
【摘要】 康拓展开: 用途:康拓展开主要用于求当前排列在所有排列中排第几(一般从零开始),也可用于搜索标记状态。 公式:ans = a( n ) * ( n - 1) ! + a( n - 1 ) * ( n - 2 ) ! + …… a( i ) * ( i - 1 ) ! +……a2 * 1! + a0 * 0! .( ps: 0! = 1 ) ....

康拓展开:

用途:康拓展开主要用于求当前排列在所有排列中排第几(一般从零开始),也可用于搜索标记状态

公式:ans = a( n ) * ( n - 1) ! + a( n - 1 ) * ( n - 2 ) ! + …… a( i ) * ( i - 1 ) ! +……a2 * 1! + a0 * 0! .( ps: 0! = 1 ) .

公式有了那就剩下求 a( n ) , a( n - 1) , a( n - 2 ) …… 了。先说一下 a( i ) 的意义,a( i ) 代表在 i 之后比 i  小的数的个数。

For example :  s = { 1 , 2 , 3 , 4 }  , 求 s1 = { 3, 2 , 4 , 1 } 在排列中排第几( 按字典序)

                       3 : 比3小且在3后面的数共有2个  ~> a3=2 ;

                       2 :    比2小且在2后面的数共有1个  ~> a2=1 ;

                       4 :    比4小且在4后面的数共有1个  ~> a1=1 ;

                       1 :    比1小且在1后面的数共有0个   ~> a0=0 ;

so ~ >      ans = 2 * 3! + 1 * 2! + 1 * 1! + 0 * 0! =  15 ( 这里排名从 0 开始 ) ;

再来一个:    s1 = { 2 , 4 , 1 , 3 }  在排列中排第几

                      2 :  比2小且在2后面的数共有1个 ~> a3 = 1 ; 

                      4 :  比4小且在4后面的数共有2个 ~> a2 = 2 ;

                      1 :  比1小且在1后面的数共有0个 ~> a1 = 0 ;

                      3 :  比3小且在3后面的数共有0个 ~> a0 =0 ;

so ~>   ans = 1 * 3! + 2 * 2! + 0 * 1 ! + 0 * 0! = 10  ;

代码:


  
  1. int Cantor(string str){
  2. int ans = 0 ;
  3. for(int i = 0 ;i < str.length() ; ++i){
  4. int temp = 0 ;
  5. for(int j = i+1 ;j < str.length() ; ++j)
  6. if(str[i] > str[j])
  7. temp++ ;
  8. ans += temp * f[str.length()-i-1] ;
  9. }
  10. return ans ;
  11. }


逆康拓展开:

用途:很明显与康拓展开相反可以求在序列中第 n 个数的序列。

For example :  序列为  s = { 1 , 2 , 3 , 4 } ,求序列中第排名为10 的序列。

                     1. 用10去除 3! 商 1 余 4 ;

                     2. 用 4 去除 2! 商 2 余 0 ;

                     3. 用 0 去除 1! 商 0 余 0 ;

                     4.  用0 去除 0! 商 0 余 0 ;

so ~ >   先看第一个数(看商): 它后面只有一个数比它小,所以这个数是2

                     第二个数: 它后面有两个数比它小,如果2不被确定为第一个数,那么这个数一定是3,因为2已经被确定为第一个数了,所以这个数就是4了

                     第三个数: 它后面有0个数比它小,那么第三个数就是1

                     第四个数: 它后面有0个数比它小,那么第三个数就是4

              所以序列为: s1 = { 2 , 4 , 1 , 3 } .

代码:


  
  1. string Incantor(int n)
  2. {
  3. string str="" ;
  4. int len = 4 ;
  5. memset(vis,false,sizeof(vis)) ;
  6. for(int i=len-1 ;i >= 0 ;i--)
  7. {
  8. int j=-1 ;
  9. for(int k=0 ;k <= n/f[i] ;k++) // f[] 为对应阶乘
  10. while(vis[++j]) ;
  11. vis[j]=true ;
  12. str +=('1'+j) ;
  13. n%=f[i] ;
  14. }
  15. return str ;
  16. }





 

文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/25068965

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。