Graveyard Design POJ2100

投稿日: 更新日:

問題:http://poj.org/problem?id=2100

問題

連続した正整数i,i+1,i+2,...i, i+1, i+2, ...を考えます。その二乗の和i2+(i+1)2+...i^2 + (i+1)^2 + ...nnと一致する数列をすべて列挙してください。

解法

尺取り法をつかう。

区間[l,r)[l, r)の二乗の和がnn未満であれば、rrを増やし、そうでなければllを増やす。総和は適宜更新していき、nnと一致した範囲を記録しておく。

二乗の和を求めているので、l,rl, rは最大でも、n\sqrt{n}までを考えれば良い。

実装

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

void solve(){
    long long n;
    cin >> n;
    long long l = 1, r = 1;
    long long sum = 0;
    vector<pair<long long, long long>> ans;
    while(l*l <= n){
        if(sum == n){
            ans.push_back(make_pair(l ,r));
        }
        if(r*r <= n && sum < n){
            sum += r*r;
            r++;
        }else{
            sum -= l*l;
            l++;
        }
    }

    cout << ans.size() << '\n';
    for(int i = 0;i < ans.size(); ++i){
        cout << ans[i].second - ans[i].first;
        for(int k = ans[i].first;k < ans[i].second; ++k){
            cout << " " << k;
        }
        cout << '\n';
    }
}

int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(0);
    solve();
    return 0;
}

書いた人

profile_image

お茶の葉

物理とプログラミングが好きな人