蓝桥杯往届试题:带分数(全排列、java)

问题描述

100 可以表示为带分数的形式:100 = 3 + 69258 / 714。

还可以表示为:100 = 82 + 3546 / 197。

注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。

类似这样的带分数,100 有 11 种表示法。

输入格式

从标准输入读入一个正整数N (N<1000*1000)

输出格式

程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。

注意:不要求输出每个表示,只统计有多少表示法!

样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6

题目要求,输入一个数,将其转换为一个整数+分数(a+b/c)的形式,且不重复地包含1~9所有数字。

解题思路:

        根据题意可知a,b,c包含了1~9所有数字且不重复,也就是说abc是数字1~9的一种排列。

        所以,我们可以先对数字数list进行全排列,然后再划分a,b,c。如果这种划分满足条件:a+b/c=number,b%c=0,就记录数+1。

这种解法的关键点在于:

        1.求出数字数list的全排列;

        2.划分数字a,b,c 各自的位数。

求全排列的方法这里采用递归分治法。递归函数,函数循环查找数组,将数字数组所有数字查找出来,每查找出一个数,就调用自己,查找出除了这个数之外数组的全排列……

数字a,b,c位数的划分:a的位数i在1和number的长度nlength之间,那么,b的第一位为s[nlength],c的最后一位为s[8],bc的长度为9-i;因为b/c为整数,所以b的长度至少为bc长度的一半,不然b/c不可能为整数。

        假设数字数list的一种全排列为s[9],a的长度为i,a的值为na,则b的最后一位可以用c的最后一位来求,即(na*s[8])%10,借b的最后一位和c的最后一位可以判断b和c的位数划分。

实现代码如下:

import java.util.Scanner;

public class Main{
	static int nlength=0;//输入整数n的长度
	static int n=0;
	static int count =0;//记录带分数个数
	static int[] s=new int[] {1,2,3,4,5,6,7,8,9};//定义数组
	public static void main(String[] args)
	{
		Scanner input=new Scanner(System.in);
		n=input.nextInt();
//		long start=System.currentTimeMillis();
		nlength=(n+"").length();//记录n的长度
		allrang(0);//数组s的全排列
		System.out.println(count);
//		long end=System.currentTimeMillis();
//		System.out.println(end-start);
	}
	public static void allrang(int k)
	{
		if(k==s.length-1)//遍历了一遍数组s
		{
			process();
			return;
		}
		else
		{
			for(int i=k;i<s.length;i++)//全排列数组s
			{
				{int temp=s[k];s[k]=s[i];s[i]=temp;}//交换前缀,使之产生下一个前缀
				allrang(k+1);//继续全排列
				{int temp=s[k];s[k]=s[i];s[i]=temp;}//将前缀交换回来,继续做上一个前缀的排列
			}
		}
	}
	public static void process()
	{
		String str="";
		for(int i=0;i<s.length;i++)str+=s[i];//将数组s转换为字符串数组str
		int a,b,c,na,bc,bl;//n=a+b/c
		for(int i=1;i<=nlength;i++)
		{
			a=dev(0, i-1);//取得a的数值
			na=n-a;//取得b/c的数值
			if(na<=0)return;
			bc=9-i;//取得b和c的位数
			bl=(na*s[8])%10;//用c的最后一位,即数组的最后一位s[8]来取得b的最后一位
			for(int j=i+bc/2-1;j<=7;j++)//b至少占有bc长度的一半,不然b/c不可能为整数
			{
				if(s[j]==bl)//找到符合的位置,即b的最后一位
				{
					b=dev(i, j);
					c=dev(j+1, 8);
					if(b%c==0&&b/c==na)
					{
						count++;
					}
					break;
				}
			}
		}
	}
	public static int dev(int a,int b)
	{
		int ans=0;
		for(int i=a;i<=b;i++)
		{
			ans+=s[i];
			ans*=10;
		}
		return ans/10;
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值