POJ 2100 Graveyard Design 尺取法

一、题目大意

给出一个数字num,1<=num<=1e14,找出连续的数字 ai,ai+1...aj使得每一项取平方最后求和等于num,题目要求排列的数字,和排列的个数,输出出来

二、解题思路

因为是平方求和,那么我们只需要计算1e7以内的数字就可以,case time limie 2000ms,简单考虑下尺取法最合适,O(n)复杂性,1e7的数组,时间上可以过。

思路如下:

初始化left和right为1,n为 10000007 (加7是为了安心),sum为0
1、当sum<num且right<n时,不断的给sum加上right的平方,然后right自增
2、如果1结束后,sum<num,程序结束
3、判断下sum和num是否相等,相等的话,记录下一组解(用vector记录简单)
4、sum减去left的平方,left自增

这个记录解的过程,可以用vector,每次找到了解,把right-left+1作为数字的数量,放在新的vector里,然后把[left,right]的闭区间内的数字都放在vector里面,再把这个vector放在大vector里就行

尺取法的left只能越来越大。所以记录解的过程就是按left递增去排序的,不需要对vector做排序

需要注意的是本题目需要开long long

三、代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll n = 10000007, num;
vector<vector<ll>> ansVector;
void output()
{
    printf("%d\n", ansVector.size());
    for (int i = 0; i < ansVector.size(); i++)
    {
        for (int j = 0; j < ansVector[i].size(); j++)
        {
            if (j + 1 == ansVector[i].size())
            {
                printf("%d\n", ansVector[i][j]);
            }
            else
            {
                printf("%d ", ansVector[i][j]);
            }
        }
    }
}
void saveAns(ll left, ll right)
{
    vector<ll> currentVector;
    currentVector.push_back(right - left + 1);
    for (ll i = left; i <= right; i++)
    {
        currentVector.push_back(i);
    }
    ansVector.push_back(currentVector);
}
void solve()
{
    ll left = 1, right = 1, sum = 0;
    while (true)
    {
        while (sum < num && right < n)
        {
            sum += (right * right);
            right++;
        }
        if (sum < num)
        {
            break;
        }
        else if (sum == num)
        {
            saveAns(left, right - 1);
        }
        sum -= (left * left);
        left++;
    }
    output();
}
int main()
{
    while (~scanf("%lld", &num))
    {
        ansVector.clear();
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值