题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
把 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来入手来寻找规律。
i | j | k |
1 | 2 | 97 |
1 | 3 | 96 |
1 | … | … |
1 | 48 | 51 |
1 | 49 | 50 |
当i=1时,j最大到49 | ||
2 | 3 | 95 |
2 | 4 | 94 |
2 | … | … |
2 | 47 | 51 |
2 | 48 | 50 |
当i=2时,j最大到48 | ||
… | … | … |
32 | 33 | 35 |
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。