题目描述
给出一个区间[a, b],计算区间内“神奇数”的个数。
神奇数的定义:如果一个数的数字组合可以分成两部分A,B,如果A部分之和等于B部分之和,则这个数是一个神奇数。
比如:242,存在[2,2]和[4],2 + 2 = 4,则242是神奇数。
输入描述:
输入为两个整数a和b,代表[a, b]区间
输出描述:
输出为一个整数,表示区间内满足条件的整数个数
输入例子:
1 50
输出例子:
4
题目解析:
神奇数的定义是,对于每一个这样的数,都可以将组成这个数的数字序列,分成A,B两个部分,A部分的和等于B部分的和,则可以得出整个数的数字序列的和’Sum = A + B = 2B’,没错,2B即代表Sum必然是一个偶数,之后我们考虑整个数字序列分为两个集合,每个数字元素都存在两种情况,在A集合或者不在A集合,所以可以分为2^n种情况,n为数字元素的个数,同时由于我们并不关注A和B的集合的有序性,比如一种情况为[2,2]或[4],另一种情况为[4]或[2,2],这里我们视为是同一种情况。所以经过分析得出,我们只需要分析的情况为 2^n / 2,考虑到每一个元素都有两种情况,我们可以用1代表存在于A集合,0代表不存在于A集合,那么当我们对每个元素的情况做一个排列,可以得到’101…10’这样一个二进制序列,而我们可以将其转化为一个整数,从而进行循环。
代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* Created by nocla on 2017/9/8.
*/
public class Algorithm_01 {
public static boolean check(int a){
List<Integer> numbers = new ArrayList<>();
int sum = 0;
while (a != 0){
numbers.add(a % 10);
sum += a % 10;
a /= 10;
}
if (sum % 2 != 0){
//如果sum为奇数,则直接返回false
return false;
}
for (int i = ((int) Math.pow(2, numbers.size())) / 2; i > 0; i--) {
int temp = 1;
//利用temp遍历每种情况的每个元素
//1011 & 0001即遍历第一个元素的情况
int sumA = 0;
for (int j = 0; j < numbers.size(); j++) {
if ((i & temp) == 0){
sumA += numbers.get(j);
}
if (sumA > sum / 2){
break;
}
temp = temp << 1;
}
if (sumA == sum / 2){
return true;
}
}
return false;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int start = in.nextInt();
int end = in.nextInt();
int cnt = 0;
for ( int i = start ; i <= end ; i++){
if (check(i)){
cnt++;
}
}
System.out.println(cnt);
in.close();
}
}