抽象的算法0.1.3.1版本
前言: 公式:(基础 + 基础 + 基础 + ...更多的基础) × 维度(影响因素) = 问题
将问题分解成一个个基础和变量,便可轻松解决问题 ————不知名的作者
题目:爱的具体形状
Fort 问 Peat 有多爱他,Peat 说我爱你就像 nn 这个数这么大。
但是 Fort 不信,他要求 Peat 具体表示出 nn 这个数字。具体表示的方式为将 nn 拆分为一个,两个或多个连续正整数之和。
Fort 认为,nn 的具体表示方式越多,Peat 就越爱他。请你帮 Fort 求出 nn 有多少种具体表示的方式。
例如,当n=9 时,有三种具体表示方式,分别为 9=9,9=4+5,9=2+3+49=9,9=4+5,9=2+3+4。
题目来源:蓝桥杯
题目分析:
第一条:数字之和等于 n
第二条:数数之间采用加法
第三条:数数之间不重复,但不同表达式数字可相同
第四条:数字最大值小于等于N
第五条:连续的一组数字
作者做了符合题目分析的三个例子
/**
* 单个例子,难以找到代码切入点
* 9 = 9
* 9 = 4 + 5
* 9 = 2 + 3 + 4
*
* 15 = 15
* 15 = 7 + 8
* 15 = 4 + 5 + 6
* 15 = 1 + 2 + 3 + 4 + 5
*
* 12 = 12
* 12 = 3 + 4 + 5
*
* @return
*/
第一组
9 = 9
9 = 4 + 5
9 = 2 + 3 + 4
第二组
12 = 12
12 = 3 + 4 + 5
第三组
15 = 15
15 = 7 + 8
15 = 4 + 5 + 6
15 = 1 + 2 + 3 + 4 + 5
现在开始找共同点
第一种写法:无法动态解决
9 = 9
12 = 12
15 = 15
第一次运算都是本身
9 = 4 + 5
12 = 3 + 4 + 5
15 = 7 + 8
第二次运算,有的数就是三数之和,有的数就是两数之和
这里作者做了一个简单的小技巧就发现了共同规律了
4 / 2 = 2 * 2
5 / 2 = 2 * 2.5
3 / 2 = 2 * 1.5
4 / 2 = 2 * 2
5 / 2 = 2 * 2.5
7 / 2 = 2 * 3.5
8 / 2 = 2 * 4
第一位数的一半是第二位数 减去 0.5
我们拿出第三次运算结果
9 = 2 + 3 + 4
15 = 1 + 2 + 3 + 4 + 5
2 / 2 = 1 * 2
3 / 2 = 1.5 * 2
4 / 2 = 2 * 2
同理,15也符合结论
看看 9 12 15 和2的关系
9 = (4.5 * 2)
9 = (2 * 2) + (2.5 * 2)
9 = (1 * 2) + (1.5 * 2) + (2 * 2)
发现没
2 + 2.5 正好 = 4.5
1 + 1.5 + 2 正好 = 4.5
第二组:
12 = (6 * 2)
12 = (1.5 * 2) + (2 * 2) + (2.5 * 2)
除它本身外,其余的差距再0.5
然后又有问题了
作者准备把1~9的列出来
1 = 1
2 = 2
3 = 3 ,1 + 2
4 = 4
5 = 5 , 2 + 3
6 = 6 , 1 + 2 + 3
7 = 7 , 3 + 4
8 = 8
9 = 9 , 4 + 5 ,2 + 3 + 4
2 + 3 + 4其实就等于 4 + 5
结合上面的0.5的差距
第一组
9 = 9
9 = 4 + 5
9 = 2 + 3 + 4
突然作者发现了一个奇妙的想法
9 / 2 = 4
4 + 1 = 5
4 + 5 = 9 ,表达式 + 1
12 = (3 + 4) + 5
9 = 5 + 4
最大的难点在于第三种情况
@Test
void contextLoads() {
int y = 1;//因为y = 本身 算一个表达式,所以从1开始
int x = 15;
for (int i = 1 ; i <= x ; i++){
// 9的倍数才有3个表达式
if(x / 9 != 0){
if (x/2 + 1 + i ==x){
y++;
}
}
if ((i + 1) + (i) == x){
y++;
}
}
System.out.println(y);
}
15的时候又不符合
15 = 15
15 = 7 + 8
15 = 4 + 5 + 6
15 = 1 + 2 + 3 + 4 + 5
看来,只能用那招了,无敌的双循环,不过会超时。。。
代码如下
public class Main {
public static void main(String[] args) {
for (int n = 1; n <= 9; n++) {
System.out.println(n + " → " + countConsecutive(n));
}
}
public static int countConsecutive(int n) {
int count = 1; // 直接包含 n = n 的情况
// 遍历起始数字 k 的范围调整为 1 到 n-1
for (int k = 1; k < n; k++) {
int sum = 0;
for (int j = k; j < n; j++) {
sum += j;
if (sum == n) {
count++;
break;
} else if (sum > n) {
break;
}
}
}
return count;
}
}
因为本身就是一个表达式,所以for循环不能用小于等于