一、题目描述
把 2019分解成 3个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?
注意交换 33 个整数的顺序被视为同一种方法,例如 1000+1001+18 和 1001+1000+18 被视为同一种。
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
二、解题思路
将2019分解成三个正整数,我们第一时间想到的就是通过三层for循环对三个正整数组合进行枚举,同时每枚举出一组正整数组合后,我们都要对这三个数进行检查,是否包含数字2或4,如果包含那么就pass掉这个组合。但这种代码实现会出现运行超时的情况,我们需要减少循环次数,那么我们可以将第一层for循环里的两层for循环减少为一层,题干中有一个重要的关注点,“例如 1000+1001+18 和 1001+1000+18 被视为同一种。”,所以三个正整数组合会因为位置不同而有三种呈现方式,我们只需取一种,因为三个正整数互不相同,所以一定会有大小关系,我们姑且选择升序的排列方式,当确定了第一个正整数i,那么我们接下来确定第二个正整数j,先让j等于i+1,然后进入while循环,得到第三个数k=2019-i-j,如果k<=j那么退出while循环,如果符合条件那么成功分解方法数加一,然后j加一,找到所有在当前i情况下所有符合条件的分解方法。
三、代码实现
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool check(int x)
{
while(x)
{
int a = x % 10;
if(a == 2 || a == 4)
{
return 0;
}
x /= 10;
}
return 1;
}
int main()
{
ll cnt = 0;
for(int i = 1; i < 2019; ++ i) //三层for循环会运行超时,所以要减少循环次数
{
int j = i + 1;
while(true)
{
int k = 2019 - i - j;
if(k <= j)
break;
if(check(i) && check(j) && check(k))
cnt++;
j++;
}
}
cout<<cnt<<endl;
return 0;
}