POJ1850 Code(组合+康托展开)

题目问一个合法字符串的字典序是第几个,合法的字符串是指里面的字符严格递增。

先判断合不合法,然后用类似康托展开的过程去求。大概过程就是用组合数算出某长度某前缀有几个,累加起来。

真难一遍写对。。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 bool islegal(char *s){
 5     for(int i=1; s[i]; ++i){
 6         if(s[i]<=s[i-1]) return 0;
 7     }
 8     return 1;
 9 }
10 long long C[27][27];
11 int main(){
12     for(int i=0; i<27; ++i) C[i][0]=1;
13     for(int i=1; i<27; ++i){
14         for(int j=1; j<=i; ++j) C[i][j]=C[i-1][j]+C[i-1][j-1];
15     }
16     char str[11];
17     scanf("%s",str);
18     if(!islegal(str)){
19         puts("0");
20         return 0;
21     }
22     int len=strlen(str);
23     long long res=0;
24     for(int i=1; i<len; ++i) res+=C[26][i];
25     bool vis[26]={0};
26     for(int i=0; i<len; ++i){
27         int j=i==0?0:str[i-1]-‘a‘;
28         for(; j<str[i]-‘a‘; ++j){
29             if(vis[j]) continue;
30             int cnt=0;
31             for(int k=j+1; k<26; ++k){
32                 if(!vis[j]) ++cnt;
33             }
34             res+=C[cnt][len-i-1];
35         }
36         vis[str[i]-‘a‘]=1;
37     }
38     printf("%lld",res+1);
39     return 0;
40 }
时间: 2024-11-08 07:45:35

POJ1850 Code(组合+康托展开)的相关文章

POJ1850 Code 【排列组合】

还不算是难题(嘿嘿,因为我做出来了) 很简单,找到相应的方程式解就是了(中间也犯了一个很2的错误,把9+10+11+...+99写成(1+90)*90/2,改过来后就好了) 不多说,code is below #include <iostream> #include <cstdio> #include <cstring> using namespace std; int combi(int a,int b) { int sum=1; int j=1; for(int i

浅谈康托展开和其逆运算

康托展开,是一种在\(\mathcal{O}(n^2)\)(\(n\)为排列元素个数)时间复杂度求解某一排列在全排列中的次序的算法. 我们以一道例题引入: 排列的序号 题目描述: 给定一个数\(n\)和一个\(n\)个数的排列\(a\),求\(a\)在\(n\)的全排列中的序号. 输入描述: 第一行一个整数\(n\),第二行一个排列\(a\). 输出描述: 求\(a\)在\(n\)的全排列中的序号. 输入输出样例: 输入 3 123 输出 1 数据范围 \(n\le 15\) 根据排列组合.加法

康托展开

对于n个数的全排列,共有n!中排列方式,如何求某一个序列在整个排列中的次序(从小到大)? 以9的全排列举例:842697513是1-9全排列的第几个?(高中数学排列组合问题,只需要做到不重不漏) 首先看第一位为8,那么第一位为1-7的全排列都比它小,共有7*8!个. 在第一位为8的情况下,其次看第二位为4,那么第二位为1-3的全排列都比它小,共有1*3*7!个. 在第一位为8,第二位为4的情况下,那么第三位为1的全排列都比它小,共有1*1*6!个. 在第一位为8,第二位为4,第三位为2的情况下,

sicily 2011. Nine Digits(广搜,康托展开)

2011. Nine Digits Constraints Time Limit: 2 secs, Memory Limit: 256 MB Description Nine tiles, each with a number from 1 to 9 on it, are packed into a 3 by 3 frame. Your task is to arrange the tiles so that they are ordered as: 1 2 3 4 5 6 7 8 9 At e

Gym10081 A - Arcade Game -康托展开、全排列、组合数变成递推的思想

最近做到好多概率,组合数,全排列的题目,本咸鱼不会啊,我概率论都挂科了... 这个题学到了一个康托展开,有点用,瞎写一下... 康托展开: 适用对象:没有重复元素的全排列. 把一个整数X展开成如下形式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0![1] 其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i]<i(1<=i<=n) 用来求全排列中这个串排第几,康托展开的逆运算就是

hdu1027(逆康托展开)

src:http://acm.hdu.edu.cn/showproblem.php?pid=1027 一开始已经提过了,康托展开是一个全排列到一个自然数的双射,因此是可逆的.即对于上述例子,在(1,2,3,4,5)给出61可以算出起排列组合为 34152.由上述的计算过程可以容易的逆推回来,具体过程如下: 用 61 / 4! = 2余13,说明a[5]=2,说明比首位小的数有2个,所以首位为3. 用 13 / 3! = 2余1,说明a[4]=2,说明在第二位之后小于第二位的数有2个,所以第二位为

数据结构——康托展开与逆康托展开

含义 康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩. 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的. 原理 X = s1(n-1)! + s2(n-2)! + s3(n-3)! + …… + sn-1 * 1! + sn * 0! 其中si表示在第i位右边比ai小的数的个数. 我们现在用sl表示第i位左边比ai小的数的个数,sr表示第i位右边比ai小的数的个数,显然可以得到如下等式: ai = sl + sr + 1 故公式中的si可以用上述等式

LG5367 「模板」康托展开 康托展开

问题描述 LG5367 题解 康托展开公式: \[ans=1+(\sum_{i=1}^{n}{a_i})\times(n-i)!\] 用树状数组维护一下\(\sum\)里面的东西,前缀积维护后面的东西. \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;char ch=1;int fh; while(ch!='

[算法总结]康托展开Cantor Expansion

[算法总结]康托展开Cantor Expansion 一.关于康托展开 1.什么是康托展开 求出给定一个由1~n个整数组成的任意排列在1~n的全排列中的位置. 解决这样问题的算法叫康托展开. 例如: \(n=4\),序列a={\(1,3,4,2\)},那么a在1~4中的全排列位置为第4个. 2.康托展开实现原理 要知道序列a排在第几位,我们就需要知道序列a之前有多少位. 我们按照上面的栗子计算: 1.比1小的数有0个,有\(0\times(4-1)!=0\)种排列. 2.比3小的数有2个,但是1