全排列散列

来源:互联网 发布:阿里云服务器支持ipv6 编辑:程序博客网 时间:2024/05/24 06:20

题目描述

       Did you remember that simple problem permutation of five? Now, TY has meeted another problem about permutation. Help him.
       You are given two numbers, n and m. The permutation is based on n digits. 
       First, you should point out the m th permutation of all permutations in an ascend order. Than reverse that permutation and print the rank of that reversed permutation of all permutations in an ascend order.

输入

Multiple cases( > 1000). Each case contains a line with two integer, n,m. (1 <= n <= 9, 1 <= m <= n!)

输出

Each case a line, the mth permutation and the rank, seperated by a space.

样例输入

5 15 10

样例输出

12345 12013452 48
#include<iostream>using namespace std;int n, m;bool used[10];int a[9];int fac[10];void  factorial(){int i;fac[0] = 1;for (i = 1; i < 10; i++)fac[i] = i*fac[i - 1];}int getNum(int i){int j,k=0;for (j = 1; k<i;j++)if (used[j] == false)k++;return j-1;}void find(){int i;for (i = 0; i < n; i++){a[i]=getNum( m / fac[n - 1-i]+1);used[a[i]] = true;m %= fac[n-i - 1];}}void turn(){int i, j;for (i = 0; i * 2 < n; i++){j = a[i];a[i] = a[n - i-1];a[n - i-1] = j;}}int which(int n){int i, j=0;for (i = 0; i < n; i++){if (used[i] == false)j++;}return j;}int toNum(){int i, k = 0;for (i = 0; i < n; i++){k += fac[n-i-1] * (which(a[i])-1);used[a[i]] = true;}return k;}int main(){//freopen("in.txt", "r", stdin);factorial();while (scanf("%d%d",&n,&m)!=-1){memset(used, 0, sizeof(used));m--;find();int i;for (i = 0; i < n; i++) printf("%d",a[i]);cout << " ";turn();memset(used, 0, sizeof(used));printf("%d\n", toNum() + 1);}return 0;}


0 0
原创粉丝点击