【组合数学】POJ-1715 Hexadecimal Numbers

前言

数学,数学,我的死穴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; 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值