题意
传送门 POJ 2100
题解
尺取法依次推进头部、尾部更新答案,由于序列连续,压缩为头尾即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
#define MAX_N 10005
using namespace std;
typedef long long LL;
struct result{
LL n, s, t; // 记录答案区间连续元素个数以及头尾位置
result(LL n, LL s, LL t):n(n), s(s), t(t){}
};
LL N;
vector<result> res;
bool cmp(result &a, result &b){
return a.n > b.n;
}
int main(){
while(~scanf("%lld", &N)){
res.clear();
LL s = 1, t = 1, sum = 0, limit = sqrt((double)N) + 1;
for(;;){
while(t < limit && sum < N){
sum += t * t;
// 推进尾部
++t;
}
if(sum == N) res.push_back(result(t - s, s, t - 1));
else if(sum < N) break;
sum -= s * s;
// 推进头部
++s;
}
sort(res.begin(), res.end(), cmp);
printf("%d\n", res.size());
for(vector<result>::iterator ite = res.begin(); ite != res.end(); ite++){
printf("%lld ", ite->n);
for(LL i = ite->s; i <= ite->t; i++) printf("%lld%c", i, i == ite->t ? '\n' : ' ');
}
}
return 0;
}