POJ 2100 · Graveyard Design【尺取法】

来源:互联网 发布:阿里云降价 编辑:程序博客网 时间:2024/05/31 13:15

【题意】
国王G最近决定重新设计一下皇陵。这个陵园必须包括两个部分:每个坟墓必须是正方形的;必须由不同数量的坟墓组成。国王G在和他的占星家们讨论一番,他决定坟墓的边长必须是连续正整数的序列。一条边长为s包含s2个坟墓。国王G想要估计现在陵园中所有尽可能满足设计条件的坟墓总数。你能帮他找到吧。
限制条件:
1n1014

【提炼】
求k组满足条件的a0ar1(每组r个数),其平方之和等于输入的正整数n

【分析】
求连续平方数之和等于给定的数n,dp或者尺取法。

题目要求存下满足条件的多组序列。

由于要提前输出组数和每组的长度,所以采用vector + pair来存数组。右戳链接

Tips:判读退出条件注意暂存一个值来判断,不然wa到你怀疑人生。

【时间复杂度】
根据完全平方数的性质,正整数n以内的完全平方数数量总数为n,所以立即推:

O(n)

【代码】

/*    coder:  Tangent Chang    date:   2017/5/11    A day is a miniature of eternity. by Emerson*/#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <string>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll;const int maxn = 10005;vector< pair<ll, ll> > ans;int main() {    ll n;    while (scanf("%lld", &n) != EOF) {        ans.clear();        ll kk = 0;        ll s = 1, t = 1, sum = 0, sq = 0;        if (n == 0) break;        while (1) {            while (sum < n) {                sq = t * t;                sum += sq;                t++;            }            if (sq > n) break;            if (sum == n) {                ans.push_back(make_pair(s, t));            }            sum -= s * s;            s++;        }        kk = ans.size();        printf("%lld\n", kk);        for (ll i = 0; i < kk; ++i) {            ll l = ans[i].first;            ll r = ans[i].second;            printf("%lld", r - l);            for (ll j = l; j < r; ++j) {                printf(" %lld", j);            }            puts("");        }    }    return 0;}
0 0