题目描述
难度分:1300
输入T(≤105)表示T组数据。每组数据输入n(1≤n≤109)。
把n表示成尽量多的合数之和。例如12=4+4+4。
输出合数的个数。如果无法做到,输出−1。
注:合数为大于1的非质数。
输入样例1
1
12
输出样例1
3
输入样例2
2
6
8
输出样例2
1
2
输入样例3
3
1
2
3
输出样例3
-1
-1
-1
算法
分类讨论
4是最小的合数,因此尽可能用更多的4来凑,分为以下几种情况:
- 如果n能够被4整除,那么就能分出n4个4,这是最优解。
- 如果n除以4余2,那么最后这个2就合并到一个4中变成6,答案是⌊n4⌋。
- 如果n除以4余1,可以枚举一下,在小于13的整数中,只有9的答案是1,其他的数都无法拆分成合数之和。而大于等于13的整数中,可以先分离出来一个13,变成13=4+9两个合数之和,剩下的部分一定可以被4整除,答案为n−134+2。
- 如果n除以4余3,可以枚举一下,小于15的整数都不可能拆分成整数之和。而大于等于15的整数中,可以先分离出一个15,变成15=6+9两个合数之和,剩下的部分一定可以被4整除,答案为n−154+2。
- 最后就是n小于4的情况,1是个非质数非合数,2和3都是质数,拆不出两个合数之和,这种情况肯定无解。
复杂度分析
时间复杂度
根据n除以4的余数,进行分类讨论,进行一个整数除法就能得到答案,时间复杂度为O(1)。
空间复杂度
只使用了有限几个变量,算法的额外空间复杂度为O(1)。
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int t, n;
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
if(n < 4) {
puts("-1");
}else {
if((n % 4) % 2 == 0) {
printf("%d\n", n / 4);
}else {
if(n % 4 == 1) {
if(n < 13) {
if(n == 9) puts("1");
else puts("-1");
}else {
printf("%d\n", (n - 13) / 4 + 2);
}
}else {
if(n < 15) {
puts("-1");
}else {
printf("%d\n", (n - 15) / 4 + 2);
}
}
}
}
}
return 0;
}