题目描述
算法1
(暴力枚举) $O(N)$
采用数组查询会比递归暴搜时间复杂度低一些(目前能过)
分析
先分析样例
样例 4 7 能组成的数k=an+bm:
0 (0个4,0个7)
4 (1,0)
7 (0,1)
8 (2,0)
11(1,1)
12(3,0)
14(0,2)
15(2,1)
16(4,0)
18(1,2)
19(3,1)
....
1.可以看到19=3×4+1×7,也可以看成在12的基础上加7,因此可以从前往后枚举每一个能组成的数(后面依靠前面的结果),枚举到足够大的数。
2.然后再根据 “大于17的任何数字都可以用4和7组合出来”,从后往前找到第一个不能被组合的数就是答案了
采用数组查询会比递归暴搜时间复杂度低一些
C 代码
#include<stdio.h>
#define MAXN 1000000
int dp[MAXN];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
dp[0]=1;
for(int i=0;i<MAXN;i++){
if(dp[i-n]&&i>=n||dp[i-m]&&i>=m) dp[i]=1;//加i>=n和i>=m防止下标越界
}
for(int i=MAXN-1;i>0;i-=2)//以2为单位递减是因为后来发现结果都是奇数
{
if(!dp[i])
{
printf("%d",i);
break;
}
}
return 0;
}
时间复杂度
执行次数约1500000次,基本由两个一层for循环组成,从算法上看是O(N)的,只是这个N比较大
算法2
(总结规律) $O(1)$
分析
根据暴力枚举的结果,输入几个数据,确定它们的最大不能组合数,我们来总结规律
n m i
2 3 1 i=(2-1)*m-2
2 5 3
2 7 5
2 9 7
2 11 9
2 13 11
3 2 1 i=(3-1)*m-3
3 4 5
3 5 7
3 7 11
3 8 13
3 10 17
3 11 19
3 13 23
4 3 5 i=(4-1)*m-4
4 5 11
4 7 17
4 9 23
4 11 29
4 13 35
4 15 41
5 2 3 i=(5-1)*m-5
5 3 7
5 4 11
5 6 19
5 7 23
5 8 27
5 9 31
5 11 39
5 12 43
111 400 43889 i=(111-1)*m-111
111 398 43669
111 397 43559
111 395 43339
111 394 43229
得出结论:由n和m最大不能组成数i=(n-1)*m-n
C 代码
#include<stdio.h>
int main(){
int n,m;
scanf("%d%d",&n,&m);
printf("%d",(n-1)*m-n);
return 0;
}
时间复杂度
O(1),根据输入的n和m,直接套用公式得出。