Problem 76
Counting summations
It is possible to write five as a sum in exactly six different ways:
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
How many different ways can one hundred be written as a sum of at least two positive integers?
加和计数
将5写成整数的和有6种不同的方式:
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
将100写成整数的和有多少种不同的方式?
生成算法:
(1) 初始序列 (1, 1, ..., 1) // 要拆分的整数m个
(2) 重复,直到序列中只剩一个元素
设当前序列为 (x_1, ..., x_{m-1}, x_m)
将 x_{m-1}, x_m 从序列中去掉。
temp = x_m + x_{m-1}
把 temp 拆成尽可能多的 x_{m-1}+1, 同时保证不出现比
x_{m-1}+1 小的项,这些项附在原序列之后。
输出序列
算法解释:
设 (x_1, ..., x_{m-1}, x_{m}) 为当前序列。在生成下一个序列时(变大),我们把最后两项融合后重新分配,分配后的序列要恰比原来大,则 x_{m-1} 处应该比原来大 1。所以把 x_{m-1}+x_m 写成带余除法的形式:
x_{m-1}+x_m = p*(x_{m-1}+1) + r |
重分配的子序列为: x_{m-1}+1, x_{m-1}+1, ..., x_{m-1}+ 1 + r
注意最后的一项是 x_{m-1}+1+r 而不是 r,否则生成的不是最小代表元。
例子: SP(6)
序列 | 带余除法 | 重分配方案 |
1 1 1 1 1 1 | 2=1*2+0 | 2 重分配为 2 |
1 1 1 1 2 | 3=1*2+1 | 3 重分配为 3 |
1 1 1 3 | 4=2*2+0 | 4 重分配为 2 2 |
1 1 2 2 | 4=1*3+1 | 4 重分配为 4 |
1 1 4 | 5=2*2+1 | 5 重分配为 2 3 |
1 2 3 | 5=1*3+2 | 5 重分配为 5 |
1 5 | 6=3*2+0 | 6 重分配为 2 2 2 |
2 2 2 | 4=1*3+1 | 4 重分配为 4 |
2 4 | 6=2*3+0 | 6 重分配为 3 3 |
3 3 | 6=1*4+2 | 6 重分配为 6 |
6 | N/A | N/A |
package projecteuler;
import junit.framework.TestCase;
public class Prj76 extends TestCase {
public static final int NUM_OF_CS = 100;
public void testCountingSummations() {
int[] arr = new int[NUM_OF_CS];
for (int i = 0; i < NUM_OF_CS; i++) {
arr[i] = 1;
}
int num = NUM_OF_CS;
long count = 1;
while (num > 1) {
int temp = 0;
int remain = 0;
int remain_num = 0;
temp = arr[num - 1] + arr[num - 2];
remain = temp % (1 + arr[num - 2]);
remain_num = temp / (1 + arr[num - 2]);
int a_num_2 = arr[num - 2] + 1;
int j = 0;
for (j = 0; j < remain_num; j++) {
arr[num - 2 + j] = a_num_2;
}
arr[num - 2 + j - 1] = a_num_2 + remain;
num = num - 2 + remain_num;
count ++;
if( count % 10000000 == 0){
print(arr, num);
}
}
// except last [100]
count -= 1;
System.out.println("count=" + count);
}
private void print(int[] arr, int num) {
for (int i = 0; i < num; i++) {
System.out.print(arr[i] + ",");
}
System.out.println();
}
}