题目描述
小香猪上算法课的时候,老师布置了一个作业题:给你一个正整数n(1 <= n <= 10,000,000),现在请问你有多少种方法能把n拆成几个连续的正整数之和。
比如n = 15:
15 = 15;
15 = 7 + 8;
15 = 4 + 5 + 6;
15 = 1 + 2 + 3 + 4 + 5;
又如 n = 10:
10 = 10;
10 = 1 + 2 + 3 + 4。输入
输入也许会有多组数据,每组数据由一行组成,每一行仅包含一个正整数n,所有输入以0结束。
输出
每一组数据对应一行输出,输出n所对应的拆分方法数。
样例输入
15 10 0样例输出
4 2
由例子中的15拆分成15=15,10拆分成10=10可以知道,拆分方法最少也有一种。
对于一个奇数输入,它必定可以被拆分成这个数除以二之后,向上取整和向下取整得到的两个正整数的和,例如15=7+8。
if (in % 2)
{
res++;
}
显然,除了上述这种15=7+8的拆分方式,其他所有拆分方式中,组成n的数都必定小于n除以二,例如15=4+5+6,4/5/6都小于7。
所以把n除以2作为寻找拆分方式的起点,逐渐向下累加并存入临时变量。如果累加之后恰好等于我们的输入n,说明这种拆分方式是对的;如果大于了n,就跳出循环,继续寻找其他拆分方式。
当组成n的拆分数中出现了1,说明之后再向下寻找的时候不可能出现新的拆分方式了,所以可以直接操作一下flag标识符,跳出两层循环。
#include <stdio.h>
int main(void)
{
int in, res = 1;
int temp;
int i, j;
int flag = 1;
int sum = 0;
scanf("%d", &in);
while (in != 0)
{
if (in % 2)
{
res++;
}
temp = in / 2;
for (i = temp; i > 0 && flag == 1; i--)
{
for (j = i; j > 0 && flag == 1; j--)
{
sum += j;
if (j == 1)
{
flag = 0;
}
if (sum == in)
{
res++;
sum = 0;
break;
}
else if (sum > in)
{
sum = 0;
break;
}
}
}
printf("%d\n", res);
res = flag = 1;
scanf("%d", &in);
}
}