蓝桥杯-算法提高-排列数

                                                                          算法提高 排列数  

                                                              时间限制: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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值