Codeforces Round #143 B. Magic, Wizardry and Wonders

なかなか解法が思いつかなかったのでとりあえず要素数5の場合を紙の上でシミュレーションしてみた。

与えられた数列を a0, a1, a2, a3, a4 とすると
 1手目 a0, a1, a2, (a3-a4)
 2手目 a0, a1, (a2-(a3-a4))
 3手目 a0, (a1-(a2-(a3-a4)))
 4手目 (a0-(a1-(a2-(a3-a4))))
最終的にこんなかんじになる。カッコとはずすと

 a0 - a1 + a2 - a3 + a4 = (a0 + a2 + a4) - (a1 + a3)

と書ける。これから

 (奇数番目の項の和)-(偶数番目の項の和)= d

となればいいとわかる。
奇数項の和を x , 偶数項の和を y とおくと、
 x - y = d
とかける。また元の配列の各要素は1以上l以下なので、奇数項の個数をp、偶数項の個数をqとおくと、
 p <= x <= l*p
 q <= y <= l*q → q <= (x-d) <= l*q
となる。この2つの式を満たすようなxを全探索で求める。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    int n,d,l;
    cin>>n>>d>>l;
    int p=(n+1)/2;
    int q=n-p;
    vector<int> odd(p), even(q);
    for(int x=p; x<=l*p; ++x) {
        int y=x-d;
        if(q<=y && y<=l*q) {
            // 奇数番目の項の和がx, 偶数番目の項の和がyになるような配列を作る
            int i=0;
            while(x>0) { odd[i%p]++; i++; x--; }
            i=0;
            while(y>0) { even[i%q]++; i++; y--; }
            break;
        }
    }
    if (odd[0]==0) { cout<<-1<<endl; return 0; }
    for(int i=0;i<n;++i) {
        if(i%2==0) cout<<odd[i/2]<<' ';
        else cout<<even[i/2]<<' ';
    }
    cout<<endl;
    return 0;
}