带分数

00 可以表示为带分数的形式: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的全排列再去判断是够满足题意即可
 关键是如何对一个排列判断,由题目式子可以看到,每个数是有一定的限制的
 首先,第一个数肯定位数小于数字n,其次,后面两个数的话,第二个数的长度肯定大于等于第三个,也就是值的大小关系。
 那么第二个数的长度肯定大于等于(总的长度减去第一个数的长度的剩下的长度的一半)
 比如:1234567989这个序列,假设第一个数为1,那么第一个数长度肯定至少大于(9-1)/2;
 为什么我们要强调长度呢,因为我的思路是转化为字符串处理的,截取函数当然要用到长度了,
 看代码吧

import java.util.*;
public class Main {
  
    static Scanner in = new Scanner(System.in);
    static int cnt;
    static boolean[] vis = new boolean[10];
    static int[] a = new int[10];
    //检查这个排列是否满足要求
    static void isOk(int n){
       int len = String.valueOf(n).length();
       String s = "";
       for(int i =0;i < 9;i++)
    		s += a[i];
       //System.out.println(s);
       int k = 0,j = 0,num1,num2,num3;
       //假设 num1 + num2/num3 = n;
       for(k = 1;k <= len;k++){//枚举第一个数num1,长度肯定不会超过n的长度
    	  num1 = Integer.valueOf(s.substring(0, k));
    	 if(num1<n){
    	   for(j = k + (9-k)/2;j < 9;j++){//枚举第二个和第三个数,第二个数的长度肯定大于等于第三个
    		  num2 = Integer.valueOf(s.substring(k,j));
    		  num3 = Integer.valueOf(s.substring(j,9));
    		  if(num2>num3&&num2%num3==0){//满足条件
    			  if(num1+num2/num3==n)
    				  cnt++;
    		   }
    	    }
    	  }    	   
       }
    }
    //数字1-9的全排列
    static void dfs(int sp,int n){
    	if(sp >= 9){
    	   isOk(n);
           return;			
    	}
    	for(int i = 1;i <= 9;i++){
    		if(!vis[i]){
    			vis[i] = true;
    			a[sp] = i;
    			dfs(sp+1,n);
    			vis[i] = false;
    		}    			
    	} 
    }
    public  static void main(String[] args) {   
       int n = in.nextInt();
       Arrays.fill(vis, false);
       long s = System.currentTimeMillis();
        cnt = 0;
        dfs(0,n);
       long e = System.currentTimeMillis();
       System.out.println(e-s);//计算程序运行时间
       System.out.println(cnt);              
    }
}

补:上面那种思路太繁琐了,这里补上更加简洁版本的代码

 思路: 由于题目是个等式,我们可以采取知二求三的方法来降低复杂度,只需要枚举整数部分和分母部分即可,然后判断数字1-9是否都曾出现过,这样简单很多,看代码:

import java.util.*;

public class Main {
    static Scanner in = new Scanner(System.in); 
    static int n,sum;
    static char[] num = {'1','2','3','4','5','6','7','8','9'};
	public static void main(String[] args) {
			n = in.nextInt();
			int i,j,t;
			String s = "";
			boolean f = false;
			for(i = 1;i < n;i++) {//整数部分
				for(j = 2;j < 10000;j++) {//分母部分
					t = (n - i) * j;//分子
					s = "" + i + j + t;
					if(s.length()!=9)
						continue;
					f = false;
					for(int k = 0;k < num.length;k++) {
						 int index = s.indexOf(num[k]);
						  if(index==-1) {//1到9之一没有出现,不符合条件
							  f = false;
							  break;
						   }
						  f = true;
					}
					if(f)
						sum++;						
			 }
		}
      System.out.println(sum);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值