全排列散列

题目描述

       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 1
5 10

样例输出

12345 120
13452 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
", toNum() + 1);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/weiyinfu/p/5013904.html