题目详情:
高斯在上小学时发明了等差数列求和公式:1+2+..+100=5050。现在问题在于给你一个正整数n,问你他可以表示为多少种连续正整数之和?(自身也算)。
输入格式:
多组数据,每组数据一行,一个正整数n。 0<n<2000000000
首先我们来看几个简单的例子:9=2+3+4;或9=4+5;
21=1+2+3+4+5+6 或 21=6+7+8 或 21= 10+11;
通过上面的例子可以发现,一个可分解的数如9,可表示成:9=9/3*3=3*3;或9=9/2*2=4.5*2;(项数是奇数时,平均数是整数,项数是偶数时,平均数+0.5是整数);
可总结为,一个可以分解成m个连续的正整数相加的正整数n,它的平均数是n/m。
所以,n可以表示为n=n/m*m; 其中,当m为偶数时,n/m+0.5必须为整数,m为奇数时,n/m必须为整数。
因此,我们只需要统计出满足上述条件的m和n/m即可求出共有多少种分解方法。
m的值从1开始判断,直到m>=sqrt(2*n)时停止。为什么是sqrt(2*n),这个应该清楚吧,因为s=1+2+....+n=(n+1)n/2;放缩一下就是根号2*n了;
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
__int64 len(__int64 n){
//求m的最后一个值;
double l=sqrt((double)n*2);
return (__int64)l;
}
int isint(double n){
//判断一个数是否是整数
if(int(n)==n)
return 1;
else
return 0;
}
int main()
{
__int64 n;
while(scanf("%I64d",&n)!=EOF){
__int64 num=0,m;
for(m=1;m<=len(n);m++){
double s=(double)n/m;
if(m%2==0&&isint(s+0.5)||m%2==1&&isint(s))
//满足条件
num++;
}
printf("%I64d\n",num);
}
return 0;
}