公平数 (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;
}