我排第几个
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
现在有"abcdefghijkl”12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的?
-
输入
-
第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个排列;
输出
- 输出一个整数m,占一行,m表示排列是第几位; 样例输入
-
3 abcdefghijkl hgebkflacdji gfkedhjblcia
样例输出
-
1 302715242 260726926
/* 康拓展开 发现忘光了 Tme:2014-8-28 12:43 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long f[14]={1,1}; void factorial(){ for(int i=2;i<=13;i++) f[i]=f[i-1]*i; } long long cantor(char *s){ long long ans=0; int l=strlen(s); for(int i=0;s[i];i++){ int num=0; for(int j=i;s[j];j++){ if(s[j]<s[i]) num++; } ans+=num*f[l-i-1];//阶乘表示的是 比它小的那个数 后边的阶乘 //每次加上比它小的个数与后边数的阶乘的乘积 比如 7 5 4 3 6 2 //第2个数 5 比它小的有 4 3 2 三个 以4为第二位 可构成的排列为 N! N表示 4 后边数字的个数 //都比以5 为第二位的小 //所以总个数即为 num*N! 个 } return ans+1; //最后加 1 ,想半天没想明白,刚好筹出来 } void solve(){ int T; factorial(); scanf("%d",&T); char s[20]; while(T--){ scanf("%s",s); printf("%lld\n",cantor(s)); } } int main(){ solve(); return 0; }
-
-
<pre name="code" class="cpp">/* 逆康拓 Time:2014-8-28 12:45 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long f[20]={1,1,2,6}; void factorial(){ for(int i=2;i<=13;i++) f[i]=f[i-1]*i; } void func (long long num){ num--; //记得要减去1 int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12}; int ans[20],x; memset(ans,0,sizeof(ans)); for(int i=0;i<=11;i++){ x=(int)num/f[11-i];//大数变小数容易出错,强制转换 //num=c1*1!+c2*2!……各个阶乘的与系数的乘积之和 //第一次取到11!的系数即第一位,阶乘与前边阶乘相差是数量级的, //直接除忽略掉小数就可以得到 //x表示之前有几个数,即取到的第几个数 ans[i]=a[x];//该数表示是第i位的数是多少,后边的阶乘会变成小数点后位数被忽略掉 for(int j=x;j<=11-i;j++)//把剩余的位数补上来 a[j]=a[j+1];//去掉取了的,往前移位 num-=x*f[11-i]; //减掉 取下一位 } for(int i=0;i<=11;i++) printf("%c",ans[i]+'a'); printf("\n"); } void solve(){ factorial(); int T; long long num; scanf("%d",&T); while(T--){ int n; scanf("%lld",&num); //printf("%lld\n",f[n]); func(num); } } int main(){ solve(); return 0; }
-
第一行有一个整数n(0<n<=10000);