前言
数学,数学,我的死穴QAQ...
老师的温馨提示:好多题都不是纯数学题,要会多种操作结合解题(例如,数学+DP/枚举/搜索...)
题目
题目描述
The base of the hexadecimal system is 16. In order to write down numbers in this system one uses 16 digits 0,1,...,9,A,B,C,D,E,F. The capital letters A,..,F stands for 10,..,15, respectively. For instance the value of the hexadecimal number CF2 is 12 * 162 + 15 * 16 + 2 = 3314 in the decimal system. Let X be the set of all positive integers whose hexadecimal representations have at most 8 digits and do not contain repetitions of any digit. The most significant digit in such a representation is not zero. The largest element in X is the number with the hexadecimal representation FEDCBA98, the second largest is the number FEDCBA97, the third is FEDCBA96 and so forth.
Write a program that: finds the n-th largest element of X;
Input
The first line of the file standard input contains integer n in the decimal representation. n does not exceed the number of elements of X.
Output
Your program should output the n-th largest element in X in the hexadecimal representation.
Sample Input
11
Sample Output
FEDCBA87
题目大意
定义一种最多8位的16进制数,每一位数字都不重复,其中16个数字分别为:
0~9,A:10,B:11,C:12,D:13,E:14,F:15
最大的数为FEDCBA98
输入一个正整数N,求第N大的数
分析
第一直觉感觉和这道题相似:Code——https://vjudge.net/contest/307619#problem/A
先说自己(稚嫩的)思路吧——
手写了一组43210的变小情况找感觉:
(1)第一位开始变小:
4 3 2 1 0
(2)第二位开始变小:
4 3 2 0 1
(3)第三位开始变小:
4 3 1 2 0
4 3 1 0 2
4 3 0 2 1
4 3 0 1 2
(4)第四位开始变小:
4 2 3 1 0
4 2 3 0 1
4 2 1 3 0
4 2 1 0 3
4 2 0 3 1
4 2 0 1 3
4 1 3 2 0
4 1 3 0 2
4 1 2 3 0
4 1 2 0 3
4 1 0 3 2
4 1 0 2 3
4 0 3 2 1
4 0 3 1 2
4 0 2 3 1
4 0 2 1 3
4 0 1 3 2
4 0 1 2 3
(5)第五位开始变小:
3 4 2 1 0
3 4 2 0 1
3 4 1 2 0
3 4 1 0 2
3 4 0 2 1
3 4 0 1 2
3 2...
写完找到了一点感觉——
(以后有时间再来解释的详细一点——>周六放假可以写)
代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
//最多8位的16进制数,每一位都不重复
//(0~9,A:10,B:11,C:12,D:13,E:14,F:15),求第n大的数
const int MAXN=20;
int vis[MAXN+5];
char num[MAXN+5]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char ans[MAXN+5];
int n,flag;
int A(int x,int y)//计算排列数A(n,m);
{
int ret=1;
if(y==0)
return 1;
while(y--)
{
ret*=x;
x--;
}
return ret;
}
void Solve(int cnt)
{
memset(vis,0,sizeof(vis));
int Acnt,Ncnt,len=0;
for(int i=1;i<=8;i++)//从高位往低位考虑
{
Ncnt=15;//对应16进制字母的下标(位置)
while(Ncnt)//一次遍历当前位所有可能的取值
{
if(!vis[Ncnt])
{
Acnt=A(15-len,8-i);
if(Acnt<cnt)
cnt-=Acnt;
else
{
vis[Ncnt]=1;
break;
}
}
Ncnt--;
}
ans[i]=num[Ncnt];
//要注意统计当前有效位的长度
if(ans[i]!='0')
flag=1;
if(flag||ans[i]!='0')
len++;
}
}
int main()
{
scanf("%d",&n);
Solve(n);
flag=0;
for(int i=1;i<=8;i++)
{
if(flag||ans[i]!='0')
{
printf("%c",ans[i]);
flag=1;
}
}
if(!flag)
printf("0");
printf("\n");
return 0;
}