"公平数"问题

公平数 (35分)
问题背景
如果一个整数的十六进制表示(不含前导0)中,前一半数字之和等于后一半数字之和,我们称它为公平数。
注意,如果该数的十六进制表示中包含奇数个数字,则正中间的数字既不属于前一半,又不属于后一半。

例如在十六进制下1+D=7+7,因此1DE77是公平数。数字E并不参与计算。
再例如,所有单个数字的十六进制数(即0~F)均为公平数,但F0不是(不能把F0补充前导0写成0F0,进而认为它是公平数)。

给出十六进制数 K, X, Y 和十六进制数字集合 S,求区间[X, Y]之内,有多少个公平数满足:

十六进制表达式(不包含前导0)中每个数字均在集合S中
并且为K的倍数

输入格式
输入第一行为数字集S,包含0~9以及大写字母A~F。
每个数字或字母最多出现一次。
第二行包含 3 个十六进制正整数K, X, Y,均不超过 10 个数字(包含0~9以及大写字母A~F,不包含前导 0)。

输出格式
仅一行,包含一个整数,即满足条件的公平数个数。

样例输入
124C
5 100 FFF

样例输出
4

样例解释
只有四个数满足条件:212,424,4C4,C1C。

 

 

算法实现如下://由于为了让你知道具体哪几个数是“公平数”,我把这些数也输出来了。

#include <stdio.h>
  
  
#include <string.h>
  
  
#include <malloc.h>
  
  

char *set = (char *)malloc(sizeof(char));
int count = 0;

void translate(char *set)//数字集大写转小写
{
	for(int i = 0; i < strlen(set); i++)
	{
		if(set[i]>='A'&&i<='F')
			set[i] = set[i] + 32;
	}
}

int num(char c)//返回单个16进制的10进制值
{
	if(c >= '0' && c <= '9')
		return (c - '0');
	else if(c == 'a')
		return 10;
	else if(c == 'b')
		return 11;
	else if(c == 'c')
		return 12;
	else if(c == 'd')
		return 13;
	else if(c == 'e')
		return 14;
	else if(c == 'f')
		return 15;
	return 0;
}

int compare(char *str1, char *str2)//比较左右两端是否 公平
{
	int sum1 = 0,sum2 = 0;
	for(int i = 0; i < strlen(str1); i++)
	{
		sum1 += num(str1[i]);
		sum2 += num(str2[i]);
	}
	if(sum1 == sum2)
	{
		count++;
		return 1;
	}
	return 0;
}

int exist(char c) //判断字符c是否存在于数字集中
{
	for(int i = 0; i < strlen(set); i++)
		if(c == set[i])
			return 1;
	return 0;
}

int judge(int n)//判断16进制数n的每个数字是否都存在于数字集中
{
	char *temp = (char *)malloc(sizeof(char));
	sprintf(temp, "%x", n);
	for(int i = 0; i < strlen(temp); i++)
	{
		if(!exist(temp[i]))
			return 0;
	}
	return 1;
}

int process(int n)//处理n是否为公平数
{
	char *temp = (char *)malloc(sizeof(char));
	char *str1 = (char *)malloc(sizeof(char));
	char *str2 = (char *)malloc(sizeof(char));
	if(judge(n))
	{
		sprintf(temp, "%x", n);
		int index = 0;
		if(strlen(temp) % 2)
		{
			for(int i = 0; i < strlen(temp) / 2; i++)
				str1[index++] = temp[i];
			str1[index] = NULL;
			index = 0;
			for(int j = strlen(temp) / 2 + 1; j < strlen(temp); j++)
			{
				str2[index++] = temp[j];
			}
			str2[index] = NULL;
			return compare(str1, str2);
		}
		else
		{
			for(int i = 0; i < strlen(temp) / 2; i++)
				str1[i] = temp[i];
			for(int j = strlen(temp) / 2; j < strlen(temp); j++)
			{
				str2[j - strlen(temp) / 2] = temp[j];
			}
			return compare(str1, str2);
		}
	}
	return 0;
}

int main(void)
{
	int k,x,y;
	scanf("%s%x%x%x", set, &k, &x, &y);
	translate(set);
	for(int i = x; i <= y; i++)
	{
		if(i % k == 0)
		{
			if(process(i))
			{
				printf("%x/n", i);
			}
		}
	}
	printf("%d/n", count);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值