算法提高 排列数
时间限制:1.0s 内存限制:256.0MB
问题描述
0、1、2三个数字的全排列有六种,按照字母序排列如下:
012、021、102、120、201、210
输入一个数n
求0~9十个数的全排列中的第n个(第1个为0123456789)。
输入格式
一行,包含一个整数n
输出格式
一行,包含一组10个数字的全排列
样例输入
1
样例输出
0123456789
数据规模和约定
0 < n <= 10!
思路:
预处理num[]数组, num[a] = a!, 表示 a 个数的排列方案数;
为方便处理,先使n--,即以 0 1 2 3 4 5 6 7 8 9 为第 0 个;
用has[]数组表示数是否已经输出过,如果 n = 3 ,n-- 为2,已经输出了 0 1 2 3 4 5 6 8 则输出8时,n - num[2]
= 0,余下的7为第一个,9为第二个数,再依次输出即可。
#include <queue>
#include <functional>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define scan(d) scanf("%d",&d)
#define scann(n,m) scanf("%d%d",&n,&m)
#define mst(a,k) memset(a,k,sizeof(a));
#define LL long long
#define eps 1e-8
#define INF 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1.)
using namespace std;
#define N 15
#define M 10005
int num[N];
bool has[N];
int main()
{
//freopen("in.txt","r",stdin);
int n;
scan(n);
n--;
num[1] = 1;
for(int i=2;i<=9;i++){
num[i] = num[i-1] * i;
}
for(int i=9;i;i--){ //输出9次。 对于第一个数后面有9个数,则每一个数都有 9!种方案
int w = n/num[i]; //对于第i位,w表示剩下数中的第几个
n -= w * num[i]; // n要减去 相应的数
int cot=0; // 记录经过了几个 未输出的数
for(int j=0;j<=9;j++){
if(!has[j]&&cot==w){ //如果该数未输出过,且经过的未输出数 cot 等于 w
has[j] = 1; //标记输出过了
cout<<j;
break;
}
if(!has[j]) cot++; // 经过的为输出数 +1
}
}
for(int i=0;i<=9;i++) if(!has[i]) cout<<i; //已经输出9个,再输出最后一个
return 0;
}