第十届蓝桥杯省赛题:把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?

第十届蓝桥杯省赛题:把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?

题目

【问题描述】
把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?注意交换 3 个整数的顺序被视为同一种方法,例如 1000+1001+18 和1001+1000+18 被视为同一种。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

我的思路

本人初步接触蓝桥杯的算法题,也没系统研究过同类题型,只是简单分享下自己的做题感悟。第一次发布博文,欢迎大家批评指正!

  1. 初步想法还是选择直接暴力拆分 ,于是考虑最大限度减少循环次数;
  2. 原理是以第一个数为三个数中最小的数依次向后遍历,遍历次数需要总数2019的三分之一即可,这里设第一个数为 i;
  3. 确定完第一个数之后,再以第二个数为剩下两个数中最小的数依次向后遍历,遍历次数需要 2019 - i 的二分之一即可,这里设第二个数为 j,第三个数为 k;
  4. 题目要求交换顺序的三个正整数不算数,于是考虑将这三个数直接从小到大排列之后再存储到结果集;
  5. 受上一个题计算子字符串个数的启发,我选用了HashMap存储结果集,存储思想就是把这三个数排序之后用+号连接转为字符串存入Map,这样可以直接避免重复值;
  6. 最后,打印出Map的size即可;

上代码

public void testInt(){
        int int0 = 2019;
        HashMap map = new HashMap();
        for(int i = 1;i<=(int0/3);i++){//其实第一个数遍历到2019的三分之一即可
            if( Integer.toString(i).contains("2") || Integer.toString(i).contains("4") ){
                continue;  //如果第一个数包含2或4则直接不考虑
            }
            for(int j = 1;j<=((int0-i)/2);j++){//其实第二个数遍历到2019-i的二分之一即可
                if( Integer.toString(j).contains("2") || Integer.toString(j).contains("4") ){
                    continue; //如果第二个数包含2或4则直接不考虑
                }
                int k = int0-i-j;
                if( Integer.toString(k).contains("2") || Integer.toString(k).contains("4") ){
                    continue; //如果第三个数包含2或4则直接不考虑
                }
                //将三个数值按从小到大排列
                //sortThree方法就是把三个数从小到大排一下然后中间用+号连接成字符串
                map.put(sortThree(i,j,k),0);
            }
        }
        System.out.println(map.size());
    }

于是乎,程序的输出是

我还挺高兴,但是查阅了好几个网上的大佬给出的结果都是40785…
草率了,把41087个结果打印出来挨个检查!
添加代码段输出Map中的值:

Set<Map.Entry<String,Integer>>set = map.entrySet();
        for(Map.Entry<String ,Integer>entry : set){
            System.out.println(entry.getKey());
        }
        System.out.println(map.size());

输出如下:

为了验证每条结果是否重复或结果不为2019的情况,我把所有数据放到了Excel里(乱入):
首先编辑公式
在这里插入图片描述
选择填充范围
在这里插入图片描述
向下填充公式
在这里插入图片描述
A列添加条件格式:重复值标红—>>添加筛选条件:按颜色筛选 ,B列按升序排序
得到如下结果:
在这里插入图片描述
结果为A列无重复值且结果均为2019…
这波大意了?!
于是乎又审了遍题目,淦!三个不同正整数的和??
改代码!

 public void testInt(){
        int int0 = 2019;
        HashMap map = new HashMap();
        for(int i = 1;i<=(int0/3);i++){//其实第一个数遍历到2019的三分之一即可
            if( Integer.toString(i).contains("2") || Integer.toString(i).contains("4") ){
                continue;  //如果第一个数包含2或4则直接不考虑
            }
            for(int j = 1;j<=((int0-i)/2);j++){//其实第二个数遍历到2019-i的二分之一即可
                if( Integer.toString(j).contains("2") || Integer.toString(j).contains("4") || i==j){
                    continue; //如果第二个数包含2或4,或者前两个数相同,则直接不考虑
                }
                int k = int0-i-j;
                if( Integer.toString(k).contains("2") || Integer.toString(k).contains("4") || i==k || j==k){
                    continue; //如果第三个数包含2或4,或者一三数相同或二三数相同,则直接不考虑
                }
                //将三个数值按从小到大排列
                //sortThree方法就是把三个数从小到大排一下然后中间用+号连接成字符串
                map.put(sortThree(i,j,k),0);
            }
        }
        System.out.println(map.size());
    }

此处添加了判断三个数中是否含相等值的条件
结果如下:
在这里插入图片描述
好的,这波可以安心的继续脱发了。

心得体会

现在还在考虑要不要参加蓝桥杯比赛,编了几道题也大概了解了些比赛时候的一点注意事项,那就是一定要冷静,然后认真审题!

这次的纠错过程整个就俩字儿

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值