1. 题目描述
Most positive integers may be written as a sum of a sequence of at least two consecutive positive integers. For instance:
6 = 1 + 2 + 3
9 = 5 + 4 = 2 + 3 + 4
but 8 cannot be so written.
Write a program which will compute how many different ways an input number may be written as a sum of a sequence of at least two consecutive positive integers.
【翻译过来】:给了一个数字,将其分解为至少2个连续整数的和的形式,那么一共有多少种方法?
2. 样例
【Input】:
The first line of input will contain the number of problem instances N on a line by itself, (1<=N<=1000) . This will be followed by N lines, one for each problem instance. Each problem line will have the problem number, a single space and the number to be written as a sequence of consecutive positive integers. The second number will be less than 2^31 (so will fit in a 32-bit integer).
【Output】:
The output for each problem instance will be a single line containing the problem number, a single space and the number of ways the input number can be written as a sequence of consecutive positive integers.
Input:
7
1 6
2 9
3 8
4 1800
5 987654321
6 987654323
7 987654325
Output:
1 1
2 2
3 0
4 8
5 17
6 1
7 23
3. 分析
拿到题目,乍一分析,已为用分治法的思想解决,即:把当前一个大的数字,将其除以2,不断分析规模较小的数字情况,从而加起来。应该用到递归的策略,但是没有找到合适的算法,于是继续分析,发现了数学规律。
【公式1】:
假设需要计算的目标数量为value,一共有以正整数n开始的j个连续的数相加,那么可以得到假设:
value=n+(n+1)+(n+2)+……+(n+j−1)
value=(n+n+j−1)∗j/2
2∗value=(n+n+j−1)∗j
n≥1=>(2n−1)≥1
2∗value≥(j+1)∗j
2∗value≥j2
因此我们可以知道,满足条件的k,即连续k个正整数相加等于N,那么k和N满足这样的关系。
【公式2】:
接下来,继续推导,由上一个推导:
value=n+(n+1)+(n+2)+……+(n+j−1)
value=j∗n+1+2+3+……+j−1
value=j∗n+(1+j−1)∗(j−1)/2
value−(1+j−1)∗(j−1)/2=j∗n
value−j∗(j−1)/2=j∗n
j与n均为正整数,则value−j∗(j−1)/2是j的倍数。
所以,一个循环遍历,直到满足公式1得到的条件:
2∗value≥j2
,代表这个数value理论上最多可以由这些整数相加而得。
在这个循环下,判断满足题意的条件,即公式2:
value−j∗(j−1)/2是j的倍数
,每满足一个这个条件的j值,计数器就记录一次这样的分法(代表此时由j个正整数相加得到),返回计数器值即可。
4. 源码
/*
* main.cpp
*
* Created on: 2017年6月8日
* Author: liboyang
*/
#include <iostream>
using namespace std;
int calculate(int value);
int main() {
int N;
int number, value;
cin >> N;
int counter = N;
while(counter > 0) {
counter--;
cin >> number >> value;
int result = calculate(value);
cout << number << " " << result << endl;
}
return 0;
}
int calculate(int value) {
int count = 0;
for (int j = 2; j * j <= 2*value; j++) {
if((value - (j-1)*j/2) % j == 0) {
count++;
}
}
return count;
}
5. 心得
这道题是纯数学题,总感觉算法期末考试有点方= =