一、题目大意
给出一个数字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做排序文章来源:https://www.toymoban.com/news/detail-705008.html
需要注意的是本题目需要开long long文章来源地址https://www.toymoban.com/news/detail-705008.html
三、代码
#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;
}
到了这里,关于POJ 2100 Graveyard Design 尺取法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!