poj 2100 尺取法(尺度法)
题意
给你一个数N
,然后找到一个连续的序列,使得这个序列中的数的平方和等于N
。
输出需要注意的是第一行为解的个数,剩下的每行先输出序列的长度,然后输出序列。按照序列的长度进行降序输出。
解题思路
没啥好说的,使用尺度法,进行枚举各个区间上的数。
需要注意的是数字1
的答案为:
1
1 1
代码实现
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const double esp=1e-6;
const int inf=0x3f3f3f3f;
const int MAXN=1E6+7;
ll n;
struct node{
ll length, begin;
//把答案放在这里,仔细一想其实不用排序,本来就是有序的。
friend bool operator< (const node &a, const node &b)
{
if(a.length == b.length)
return a.begin < b.begin;
else return a.length > b.length;
}
};
node nod[MAXN];
int main()
{
cin>>n;
ll lt=1, rt=2, sum=1;
int cnt=0;
while(1)
{
while(sum < n && rt <= ll( sqrt(n) + 1) )
{
sum+=rt*rt;
rt++;
}
if(sum < n) break;
if(sum==n)
{
nod[cnt].begin=lt;
nod[cnt++].length=rt-lt;
}
sum-=lt*lt;
lt++;
}
// sort(nod, nod+cnt);
cout<<cnt<<endl;
for(ll i=0; i<cnt; i++)
{
lt=nod[i].begin;
cout<<nod[i].length;
for(ll j=lt; j<lt+nod[i].length; j++)
{
cout<<" "<<j;
}
cout<<endl;
}
return 0;
}