题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?
注意交换 3 个整数的顺序被视为同一种方法,例如 1000+1001+18 和 1001+1000+18 被视为同一种。
实现代码
1、优化版本,运行时间比较短
#include<bits/stdc++.h>
using namespace std;
// 判断这个数有没有2或者4
int chk(char* s)
{
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]=='2'||s[i]=='4')
{
return false;
}
}
return true;
}
int main()
{
int n=2019;
int count=0;
char s[10]={0};
// 遍历到2019,加和是n就count++
for(int i=1;i<n;i++)
{
sprintf(s,"%d",i);
if(chk(s)==false)
{
continue;
}
for(int j=i+1;j<n;j++)
{
sprintf(s,"%d",j);
if(chk(s)==false)
{
continue;
}
int k=n-i-j;
sprintf(s,"%d",k);
if(chk(s)==false)
{
continue;
}
if(j<k)
{
count++;
}
//count++;
}
}
cout<<count;
}
2、无优化,(比较)暴力解
#include<bits/stdc++.h>
using namespace std;
// 判断这个数有没有2或者4
int chk(char* s)
{
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]=='2'||s[i]=='4')
{
return false;
}
}
return true;
}
int main()
{
int n=2019;
int count=0;
char s[10]={0};
// 遍历到2019,加和是n就count++
for(int i=1;i<n;i++)
{
sprintf(s,"%d",i);
if(chk(s)==false)
{
continue;
}
for(int j=i+1;j<n;j++)
{
sprintf(s,"%d",j);
if(chk(s)==false)
{
continue;
}
for(int k=j+1;k<n;k++)
{
sprintf(s,"%d",k);
if(chk(s)==false)
{
continue;
}
if(i+j+k==n)
{
count++;
}
}
}
}
cout<<count;
}
解题思路
这个题看起来人畜无害很简单,但是很多烦的地方。比如它规定数字中不能有 2 和 4,对于这种要求了数字是多少的题我总是招架不来,水平太次了……
未优化的思路就是三个循环暴力解,因为不需要重复解,所以在 for 循环内部可以先简单优化一下,让每一个循环变量从前一个开始。然后在循环内部判断数字是否包含 2 或者 4 ,最后的循环内部判断三个数加起来是否为 2019 ,如果是,count++,最后输出。
优化后的思路是进行两次循环,第三个数通过前两次循环算出来,再判断是否有 2 或者 4,然后约束其比第二个数大,就可以了。
注意点
- 注意判断这个数是否有 2 或者 4。
- 注意每个循环内部都要对数字判断。
- 注意优化后的思路,第三个数算出来之后还要比第二个数大,不然会多很多。
知识点
sprintf
函数的用法:把后面的数格式化以后存到前面的 char 型数组内。
- 判断某个数内部是否有特定数字:
// 判断这个数有没有2或者4
int chk(char* s)
{
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]=='2'||s[i]=='4')
{
return false;
}
}
return true;
}