E. Kuroni and the Score Distribution(思维 + 找规律)

题目:传送门

题意:让你构造一个长度为 n 的序列,使得 1 < a1 < a2 < ...... < an <= 1e9,且满足 1 < i < j < k <= n && a[ i ] + a[ j ] = a[ k ] 这样的三元组恰好只有 m 个,如果不能构造输出 -1.

思路:

首先,让所有 a[ i ] = i,这样的话,三元组共有 (i - 1) /  2  (i 从 1 到 n) 累加起来 个,且这个是最多的个数。那如果 m 大于累加得到的答案, 那么就不可能构造得出。(比赛的时候发现了这个规律)。

这样的话,如果 m 恰巧等于某一段前缀和,那答案就很显然了,现在需要解决的是 m 不等于某一段前缀和的情况。这里需要发现另一个规律。

你前 j 个都让 a[ j ] = j,然后你 a[ i ] 如果等于 i,那么会增加 (i - 1) / 2 组三元组,然后你会发现,你 a[ i ] = i + 2,你会增加 ( i - 3 ) / 2 组三元组,也就是说,你 i 每增加 2,你增加的三元组个数就减少 1,那就好办了,直接枚举某一段前缀和,然后构造出来,后面的就填那些不可能和前面的构成三元组的数就行了。

#include <bits/stdc++.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std;

const int N = 1e6 + 5;

int a[N];

void solve() {

    int n, m;
    scanf("%d %d", &n, &m);

    int res = 0;
    rep(i, 1, n) {
        res += (i - 1) / 2;
        if(res >= m) {
            rep(j, 1, i - 1) printf("%d ", j);
            printf("%d ", i + (res - m) * 2);
            int now = 500000000;
            rep(j, i + 1, n) printf("%d ",  now), now += 5000;
            return ;
        }
    }
    puts("-1"); return ;
}

int main() {

//    int _; scanf("%d", &_);
//
//    while(_--) solve();

    solve();

    return 0;

}

猜你喜欢

转载自www.cnblogs.com/Willems/p/12410554.html