标题:带分数
100 可以表示为带分数的形式:100 = 3 + 69258 / 714
还可以表示为:100 = 82 + 3546 / 197
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
题目要求:
从标准输入读入一个正整数N (N<1000*1000) 程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
例如: 用户输入:
100
程序输出:
11
再例如: 用户输入:
105
程序输出:
6
资源约定: 峰值内存消耗(含虚拟机) < 64M CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
分析:
直接枚举即可,枚举所有1-9可能的组合形式,然后用运算符去分割,与结果匹配即为一种方案。
-
构建1~9个数的所有排列
-
找出整数,分母,分子各自的位数范围
-
写出由数组位数求出该数的值的算法 (可类比求逆序数的算法)
-
暴力搜索统计即可!
注意事项:
1.整数位数最大只能为7
2.分子位数必须大于分母位数
3.分母位数不能没有
4.最后判断 整数+分子/分母 == N&&分子%分母 ==0 缺一不可!!
代码:
import java.util.Scanner;
public class Main {
static int ans; //用于记录答案
static int N; //输入的整数
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
int [] arr = {1,2,3,4,5,6,7,8,9};
//int [] arr = {1,2,3};
permutation(arr,0); //对arr数组的数字进行全排列
System.out.println(ans);
}
//确认某一个排列的第k位
private static void permutation(int[] arr, int k) {
//全部确认时
if(k == arr.length) {
check(arr); //枚举加号和除号的位置,检查是否满足带分数的条件
/*打印出全排列
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
System.out.println();*/
return;
}
//选定第k位,
for(int i = k; i < arr.length; i++) {
//将第i位和第k位进行交换
int temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
// 移交下一层去确认k+1位
permutation(arr, k+1);
//回溯(换回来)
temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
}
//枚举加号和除号的位置
private static void check(int[] arr) {
//+前的字符数最多是7,至少留一个空位放/号
for (int i = 1; i <= 7; i++) {
int num1 = toInt(arr,0,i);//+号前面的一段整数
//如果此时+号左边的数额已经不小于N,则没必要验算了
if (num1 >= N) {
continue;
}
// /前面的字符数
for (int j = 1; j <= 8-i; j++) {
int num2 = toInt(arr, i, j); //分子
int num3 = toInt(arr, i+j, 9-i-j); //分母
if(num2 % num3 == 0 && num1 + num2 / num3 == N) {
ans++;
}
}
}
}
//将数组元素转换成整数
private static int toInt(int[] arr, int pos, int len) {
int t = 1;
int n = 0;
for (int i = pos + len - 1; i >= pos; i--) {
n += arr[i] * t;
t *= 10;
}
return n;
}
}