蓝桥杯 数的分解

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

        把 2019分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?

        注意交换 3个整数的顺序被视为同一种方法,例如 1000+1001+18和 1001+1000+18 被视为同一种。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

我的解题思路:

分析题目

        1)题目要求将2019分解为三个不同的正整数(0不是正整数,且i+j+k=2019)

        2)交换 3个整数的顺序被视为同一种方法

        3)每个数都不包括2和4

        这道题一开始我并没有思路,也找不到题目的突破口,于是就去搜题解了。

题解一 暴力解题

        通过三层循环(循环变量分别为i,j,k),从1到2019。寻找所有符合题目要求的分解数,符合一次,count+1。

       针对条件(1),如果i=j或者i=k或者j=k,退出当前循环,为了减少不必要的循环次数,i=j可在第二重循环的开头就判断。

       针对条件(2),对最终计算出的count值除以6,即重复的部分(3!),因为分解的三个数有六种排序算一种情况。(这个想法我当时没想到)

        针对条件(3),单独写一个方法来判断这三个数中是否含2和4。该方法在第三重循环中调用。

        方法实现如下:

      (学习到如何判断一个数中是否含有某个数,或如何求到一个数的每一位数)

 public static boolean jugdge(int a){
		  while(a>0){
		    if(a%10==2||a%10==4) return false;
		    a=a/10;
		  }
		  return true;
	}

          整体代码如下:

import java.util.*;
public class Main{
   public static void main(String args[]){
      int count=0;
      for(int i=1;i<2019;i++){
          for(int j=1;j<2019;j++){
              if(i==j) continue;
              for(int k=1;k<2019;k++){
                  if(k==j||k==i) continue;
                  if(i+k+j==2019&&judge(i)&&judge(j)&&judge(k))
                     count+=1;
              }
          }
      }
      System.out.println(count/6);
   }
   public static boolean judge(int a){
      while(a>0){
         if(a%10==2||a%10==4) return false;
         a/=10;
      }
      return true;
   }

}

题解二 优化题解

        我看到了一篇写的不错的博客,他对这题的解题过程有着很清晰的解释。but,我找不到那篇博客了。

        我们可以换一种思路来满足条件(2)。我们可以从小一点的数100来入手来寻找规律。

ijk
1297
1396
1
14851
14950
当i=1时,j最大到49
2395
2494
2
24751
24850
当i=2时,j最大到48
323335
i最大为32

       由上表分析可知,要想不重复,就保证i<j<k。故i从1开始,到最大值100/3-1结束;j从i+1开始,到最大值100/2-1结束;因为i和j确定,故k也随之确定,则k=100-i-j(这样循环便可少一个)。

        如何求临界值:设i的临界值为X,则X+X+1+X+2=2019,求得X=672。

                                  或者i的临界值为2019/3-1。

                                  j的临界值为2019/2-1=1008。

        因为每次j都会循环到1008,此时k可能为负数,故需要判断条件k>0;

        i,j已经控制在一定范围内了,且足以保证i<j,但k没有限制,故还应添加限制k>j。

        再满足条件(1)(3)即可得到答案。完整代码如下:

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
        public static void main(String args[]) {
	        int count=0;
	        int num=2019;
	        for(int i=1;i<=num/3-1;i++){
	          for(int j=i+1;j<=num/2-1;j++){
	            int k=num-i-j;
              if(i==j||k==i||k<=j) continue;
	            if(jugdge(i)&&jugdge(j)&&jugdge(k)) count+=1;
	          }
	        }
	        System.out.println(count);//在此输入您的代码...
	      
	}
	 public static boolean jugdge(int a){
		    while(a>0){
		    if(a%10==2||a%10==4) return false;
		    a=a/10;
		  }
		  return true;
	}
    }

此题收获

       在没有思路时先把题目的要求罗列出来,然后想办法满足题目要求,将最直接的方法或想法写出来,在分析有何不足,如何优化。将一个大的问题先换成小的问题和实例来寻找规律,最后在抽象。我自己做的优化是在第三重循环,我并未循环k而是让k值等于2019-i-j;这样更加节约时间,当然对应的k的条件限制要改为k>j。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值