King George has recently decided that he would like to have a new design for the royal graveyard. The graveyard must consist of several sections, each of which must be a square of graves. All sections must have different number of graves.
After a consultation with his astrologer, King George decided that the lengths of section sides must be a sequence of successive positive integer numbers. A section with side length s contains s 2 graves. George has estimated the total number of graves that will be located on the graveyard and now wants to know all possible graveyard designs satisfying the condition. You were asked to find them.
2030
2 4 21 22 23 24 3 25 26 27
因为本人比较菜,,,刚接触算法,所以对很多不是很了解。这个题刚看到的时候有点蒙,不知道怎么做,看了一下教程知道是典型的尺取法。但这个代码是看完别人的按照自己的思维打出来的,先解释一下。题意说是给定一个数字,找出连续的正整数的平方的和跟它相等。尺取法这个的大致意思是从r=1开始,sum+=r*r,r++,在r递增的时候从1开始的平方和sum也递增,直到sum大于输入的数字n,在大于之后说明前面的小的数字的平方和应该丢掉一些,所以从l=1开始在sum里边减去递增的l的平方,直到减到sum<n再一次发生,然后在在原来的基础上递增r使其的平方和加到sum里边使sum再一次增大大于n,然后通过l的增使sum减小,用r的增大让sum增大,不断使中间数的平方和趋近与n直到sum=n。这里面有两个判断条件:第一个是sum==n,这个条件成立就说明已经找到了想要的数字,此时记录在二维数组里等待输出。还有一个判断条件就是ap=r*r与n的大小关系,代码中我转换成t(n的平方根)和r的大小关系是一样的。如果单独的r已经大于t了的话,再循环也就没意义了,肯定不会存在连续的数字平方的和来输出,所以这应该作为循环结束条件来使用。最后还需要在输出的时候思考一下,此处不再赘述。代码如下:
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int main()
{
int i=1,j;
long long int a[10000][2],n,ap=0,t,sum=0,k,l=1,r=1;
scanf("%I64d",&n);
t=(int)sqrt(1.0*n);
while(l<=t)
{
while(ap<n&&sum<n)
{
ap=r*r;
sum+=ap;
r++;
}
if(sum==n)
{
a[i][0]=l;
a[i][1]=r;
i++;
}
sum-=l*l;
l++;
}
printf("%d\n",i-1);
for(j=1;j<i;j++)
{
printf("%I64d ",a[j][1]-a[j][0]);
for(k=a[j][0];k<a[j][1];k++)
{
printf("%I64d ",k);
}
printf("\n");
}
return 0;
}