Graveyard Design(尺取法)

Graveyard Design(尺取法)

题目描述

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 s2 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.
Input
Input file contains n — the number of graves to be located in the graveyard (1 <= n <= 1014 ).
Output
On the first line of the output file print k — the number of possible graveyard designs. Next k lines must contain the descriptions of the graveyards. Each line must start with l — the number of sections in the corresponding graveyard, followed by l integers — the lengths of section sides (successive positive integer numbers). Output line’s in descending order of l.

Sample Input
2030

Sample Output
2
4 21 22 23 24
3 25 26 27

题意:给出坟墓的总数量,找出能划分出的所有边长连续的正方形,所有正方形的面积之和恰好等于坟墓的数量,找出所有这样的正方形,输出一共有几组,按每组正方形个数从大到小每行输出一组正方形的数量,每个正方形的边长。

题解:找的是一段连续的区间,考虑用尺取法来做,这里需要注意的是n的范围很大,一开始我把所有的数给打表,结果内存超限,其实因为边长都是连续的,每次只需要保留符合要求的每组正方形的左右端点就可以了,然后利用for循环在最后输出。

#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <vector>
#include <map>
#include <set>
using namespace std;
int len[50000],l2[50000],r2[50000];   //分别保存每组正方形个数、左端点和右端点;
int main()
{
    long long n;
    scanf("%lld",&n);
    long long l=1,r=0;
    long long sum=0;
    int countt=0;
    while(1)
    {
        while(sum<n)
        {
            r++;
            sum+=r*r;
        }
        if(r*r>n)       //循环结束条件;
            break;
        if(sum==n)
        {
            len[countt]=r-l+1;
            l2[countt]=l;
            r2[countt]=r;
            countt++;
        }
        sum-=l*l;
        l++;
    }
    //cout<<r<<endl;
    printf("%d\n",countt);
    for(int i=0; i<countt; i++)   //注意输出格式;
    {
        printf("%d",len[i]);
        for(int j=l2[i]; j<=r2[i]; j++)
            printf(" %d",j);
        printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值