带分数(蓝桥杯JavaB组预赛)

本文转自http://blog.csdn.net/keepthinking_/article/details/8947014

因为这位同学解释的相当明白,还给了详尽的代码,于是直接转载过来。看来以后再写博客的时候还是要认真点,多跟别人学习啊


标题:带分数
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,否则按无效代码处理。

分析:这道题初看起来第一感觉就是用暴力破解应该可以搞定,但是时间复杂度应该会相当可观,仔细观察,会发现这道题无非是全排列的一种运用,把等式定义为:

N=A+B/C ,则ABC组合在一起就是1到9的一个全排列,所以可以把问题转换成对于一个9位数的数字,如何将其划分为A、B、C三部分,使得其满足N=A+B/C(隐含条件:

B%C==0),对于一个9位数可以这样考虑:A是不可能大于N的,所以A的位数只可能是从1位到和N相同位数这个范围,确定了A的位数之后,剩下的就是B和C的总位数,

B数字的开始位置即A数字的下一位,C数字的最后一位就是整个9位数的最后一位,那如何确定B的结束位置呢?

这里有个小技巧,可以大大减少可能性的判断:

假设A的结束位置为 aEnd,则aEnd+1~9就是B和C的位置,在这个位置范围内,B最少占据了一半的数字,否则B/C就不能整除了,所以可以从aEnd+1~9的中间位置开始

确定B的结束位置,这时候可以从中间位置开始向后确定B的结束位置,一直到8的位置,确定了B的结束位置,则A、B、C三个数字的具体值就都可以确定了,判断是否符

合等式N=A+B/C,符合则输出。

以上确定B的结束位置的方法其实不怎么好,因为还是会浪费一些时间(自己模拟下就知道了),不过已经可以在规定的时间内得出答案了。

这里再介绍一种确定B结束位置的方法,可以让性能再提高一些:


观察等式:N=A+B/C,可以转换成==》B=(N-A)*C,N和A确定了(先确定A的结束位置后,再来确定B的结束位置的),C的最后一个数字确定了(整个9位数最后一位),即可以确定B最后一个数字了(这里将其定义为BL),这样可以从以上的aEnd+1~9的中间位置开始找,直到8,当数字为BL时,则判读是否符合等式:N=A+B/C,可以想想,其实这种等于BL的位置至多有一次(因为数字1到9不能重复出现),所以第一次找到和BL匹配的数字的时候就不用再往后找了。用这种方法,提高的性能还是非常可观的!

思想其实挺简单,想不到打成字这么麻烦,将就着看吧,以下为java版的代码:

[java]  view plain copy
  1. import java.util.Scanner;  
  2.   
  3. public class ys_09 {  
  4.       
  5.     public static void main(String[] args) {  
  6.         //将等式定义为:N=A+B/C  
  7.         Scanner scanner=new Scanner(System.in);  
  8.         N=scanner.nextInt();  
  9.         long start=System.currentTimeMillis();  
  10.         int[] s=new int[]{1,2,3,4,5,6,7,8,9};  
  11.         NLength=(N+"").length();  
  12.         allRange(s, 0, s.length-1);  
  13.         long end=System.currentTimeMillis();          
  14.         System.out.println("耗时:"+(end-start)+" ms");  
  15.         System.out.println("总数为:"+kinds+" 种");    
  16.     }  
  17.     public static int N;  
  18.     public static int NLength;//N数字的长度  
  19.     public static int kinds;  
  20.     public static void process(int[] s){  
  21.         String str="";  
  22.         for(int i=0;i<9;i++) str+=s[i];  
  23.         int A,B,C,NMA,BC,BMCL,BLastNumber;  
  24.         //A的位数  
  25.         for(int i=1;i<=NLength;i++){  
  26.               
  27.             /* 
  28.             //方法1 
  29.             A=Integer.valueOf(str.substring(0, i)); 
  30.             NMA=N-A;//N减去A的值 
  31.             if(NMA<=0)return; 
  32.             BC=9-i;//B和C还有多少为可用 
  33.             BMCL=(NMA+"").length();//B/C的长度  
  34.             //确定的B的结束为止 
  35.             for(int j=i+BC/2;j<=8;j++){//可以优化这里 
  36.                 B=Integer.valueOf(str.substring(i,j)); 
  37.                 C=Integer.valueOf(str.substring(j,9)); 
  38.                 if(B%C==0&&B/C==NMA){ 
  39.                     kinds++; 
  40.                     System.out.println(N+"="+A+"+"+B+"/"+C); 
  41.                 } 
  42.             } 
  43.             */  
  44.               
  45.             //方法2  
  46.             A=Integer.valueOf(str.substring(0, i));  
  47.             NMA=N-A;   
  48.             if(NMA<=0)return;  
  49.             BC=9-i;//B和C总共多少位  
  50.   
  51.             BLastNumber=(NMA*s[8])%10;//B最后的数字  
  52.             //j为B最后一个数字的位置  
  53.             //B最少占有B和C全部数字的一半,否则B/C不可能为整数  
  54.             for(int j=i+BC/2-1;j<=7;j++){  
  55.                 //找到符合的位置  
  56.                 if(s[j]==BLastNumber){  
  57.                     B=Integer.valueOf(str.substring(i,j+1));  
  58.                     C=Integer.valueOf(str.substring(j+1,9));  
  59.                     if(B%C==0&&B/C==NMA){  
  60.                         kinds++;  
  61.                         System.out.println(N+"="+A+"+"+B+"/"+C);  
  62.                     }  
  63.                     //符合要求的位置只可能出现一次  
  64.                     break;  
  65.                 }  
  66.             }  
  67.         }  
  68.     }  
  69.     public static void swap(int[] s,int a,int b){  
  70.         if(a==b)return;  
  71.         int tmp=s[a];  
  72.         s[a]=s[b];  
  73.         s[b]=tmp;  
  74.     }  
  75.     //全排列  
  76.     public static void allRange(int[] s,int k,int m){  
  77.         if(k==m){  
  78.             process(s);  
  79.             return;  
  80.         }  
  81.         else{  
  82.             for(int i=k;i<=m;i++){  
  83.                 swap(s,k,i);  
  84.                 allRange(s, k+1, m);  
  85.                 swap(s,k,i);  
  86.             }  
  87.         }  
  88.     }  
  89. }  

输入:100

输出:

[java]  view plain copy
  1. 100=3+69258/714  
  2. 100=82+3546/197  
  3. 100=81+5643/297  
  4. 100=81+7524/396  
  5. 100=94+1578/263  
  6. 100=96+2148/537  
  7. 100=96+1428/357  
  8. 100=96+1752/438  
  9. 100=91+5742/638  
  10. 100=91+5823/647  
  11. 100=91+7524/836  
  12. 耗时:554 ms  
  13. 总数为:11 种  


另外补充一份C语言实现的代码:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <time.h>  
  4.   
  5. int number, n = 0;  
  6. int list[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};  
  7.   
  8. int test;  
  9.   
  10. void swap(int *a, int *b)  
  11. {  
  12.     int temp = *a;  
  13.     *a = *b;  
  14.     *b = temp;  
  15. }  
  16.   
  17. int getNum(int s, int an)  
  18. {  
  19.     int i, num = 0;  
  20.     for (i = s; i <= an; i++)  
  21.     {  
  22.         num = list[i] + num * 10;  
  23.     }  
  24.     return num;  
  25. }  
  26.   
  27. void perm(int k, int m, int x)  
  28. {  
  29.     int i, j, a, b, c;  
  30.       
  31.     if (k > m)  
  32.     {  
  33.         for (i = 0; i < x; i++)  
  34.         {  
  35.             a = getNum(0, i);  
  36.             test=((number-a)*list[8])%10;  
  37.             for (j =i+(8-i)/2; j < 8; j++)  
  38.             {  
  39.                 if(list[j]==test)  
  40.                 {  
  41.                     b = getNum(i + 1, j);  
  42.                     c = getNum(j + 1, 8);  
  43.                     if (b % c == 0 && a + b / c == number)  
  44.                     {  
  45.                         n++;  
  46.                     }  
  47.                     break;  
  48.                 }  
  49.             }  
  50.               
  51.         }  
  52.           
  53.     }  
  54.     else  
  55.     {  
  56.         for (i = k; i <= m; i++)  
  57.         {  
  58.             swap(&list[k], &list[i]);  
  59.             perm(k + 1, m, x);  
  60.             swap(&list[k], &list[i]);  
  61.         }  
  62.     }  
  63. }  
  64.   
  65. int main()   
  66. {  
  67.     clock_t s1, s2;  
  68.     int temp, x;  
  69.     while(scanf("%d", &number) != EOF && number != 0)  
  70.     {  
  71.         x = 0;  
  72.         temp = number;  
  73.         s1 = clock();  
  74.         n = 0;  
  75.         while (temp != 0)   
  76.         {  
  77.             x++;  
  78.             temp /= 10;  
  79.         }  
  80.         perm(0, 8, x);  
  81.         printf("total:%d\n", n);  
  82.         s2 = clock();  
  83.         printf("%f ms\n", (double)(s2 - s1));  
  84.     }  
  85. }  
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
2022蓝桥杯javab真题解析如下: 2022年蓝桥杯javab真题从基础到进阶,难度适中,测试了参赛选手在Java编程语言方面的知识和能力。题目涵盖了数、字符串处理、面向对象编程等多个知识点,考察了学生的编程思维和解决问题的能力。 首先,题目要求实现一个学生成绩管理系统,包括学生信息录入、成绩查询、成绩统计等功能。通过类的设计和实例化,可以实现学生对象的创建和信息存储。使用数或集合来存储多个学生对象,便于后续的查询和统计操作。 其次,题目要求实现一个简单的买卖股票的交易系统。需要设计一个股票类,其中包括股票名称、日期、买入价、卖出价等属性,然后通过输入的交易数据进行统计,计算利润最大化的买入和卖出操作。可以使用循环和条件语句来实现逻辑判断和计算运算。 最后,题目要求实现一个小型的计算器程序。可以通过实现不同的方法来实现加、减、乘、除等基本运算。可以使用条件语句或循环语句来判断用户输入的操作,并进行相应的计算操作。 总结来说,2022蓝桥杯javab真题考察了参赛选手的编程能力和应用基础知识的能力,要求实现多个功能,并考察了类的设计和对象的使用。通过解析这些真题,可以提高对Java编程语言的理解和应用能力,对于参加类似的编程竞赛有一定的帮助作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值