A – Takahashikun, The Strider
SB 题,不解释。
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
scanf("%d", &x), printf("%d\n", 360 / gcd(x, 360));
// A.cpp
#include <bits/stdc++.h>
using namespace std;
int x;
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
int main()
{
scanf("%d", &x), printf("%d\n", 360 / gcd(x, 360));
return 0;
}
// A.cpp
#include <bits/stdc++.h>
using namespace std;
int x;
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
int main()
{
scanf("%d", &x), printf("%d\n", 360 / gcd(x, 360));
return 0;
}
B – Extension
不难,直接容斥即可。
const int MAX_N = 3030, mod = 998244353;
int n, m, a, b, dp[MAX_N][MAX_N];
scanf("%d%d%d%d", &a, &b, &n, &m);
for (int i = a; i <= n; i++)
for (int j = b; j <= m; j++)
dp[i][j] = (0LL + 1LL * dp[i - 1][j] * j % mod + 1LL * dp[i][j - 1] * i % mod + mod - 1LL * dp[i - 1][j - 1] * (i - 1) % mod * (j - 1) % mod) % mod;
printf("%d\n", dp[n][m]);
// B.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 3030, mod = 998244353;
int n, m, a, b, dp[MAX_N][MAX_N];
int main()
{
scanf("%d%d%d%d", &a, &b, &n, &m);
dp[a][b] = 1;
for (int i = a; i <= n; i++)
for (int j = b; j <= m; j++)
if (i != a || j != b)
dp[i][j] = (0LL + 1LL * dp[i - 1][j] * j % mod + 1LL * dp[i][j - 1] * i % mod + mod - 1LL * dp[i - 1][j - 1] * (i - 1) % mod * (j - 1) % mod) % mod;
printf("%d\n", dp[n][m]);
return 0;
}
// B.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 3030, mod = 998244353;
int n, m, a, b, dp[MAX_N][MAX_N];
int main()
{
scanf("%d%d%d%d", &a, &b, &n, &m);
dp[a][b] = 1;
for (int i = a; i <= n; i++)
for (int j = b; j <= m; j++)
if (i != a || j != b)
dp[i][j] = (0LL + 1LL * dp[i - 1][j] * j % mod + 1LL * dp[i][j - 1] * i % mod + mod - 1LL * dp[i - 1][j - 1] * (i - 1) % mod * (j - 1) % mod) % mod;
printf("%d\n", dp[n][m]);
return 0;
}
C – Shift
考虑把 0
看作分隔符,然后可以把操作看成把一个段内的 1
放到另外一个段里面然后造出一个新的字符串。这个东西可以考虑 DP,设置 dp[i][j][k]
为到前 \(i\) 个单元、放了 \(j\) 个\(1\) 且操作次数为 \(k\)。考虑暴力转移 + 剪枝,就能过了。
const int MAX_N = 330, mod = 998244353;
int threshold, len, n, pre[MAX_N], dp[MAX_N][MAX_N][MAX_N], units[MAX_N];
scanf("%s%d", str + 1, &threshold), len = strlen(str + 1);
int last_pos = 0, ones = 0;
for (int i = 1; i <= len; i++)
for (int i = 1; i <= len + 1; i++)
units[++n] = i - last_pos - 1, last_pos = i;
for (int i = 1; i <= n; i++)
pre[i] = pre[i - 1] + units[i];
dp[0][0][0] = 1, threshold = min(threshold, ones);
for (int i = 0; i < n; i++)
for (int j = pre[i]; j <= pre[n]; j++)
for (int k = 0; k <= threshold; k++)
for (int g = max(j, pre[i + 1]); g <= pre[n]; g++)
if (k + g - j - units[i + 1] <= threshold)
if (i + 1 == n && g - j > units[i + 1])
int cost = g - j <= units[i + 1] ? 0 : g - j - units[i + 1];
dp[i + 1][g][k + cost] = (0LL + dp[i + 1][g][k + cost] + dp[i][j][k]) % mod;
for (int i = 0; i <= threshold; i++)
ans = (0LL + ans + dp[n][ones][i]) % mod;
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 330, mod = 998244353;
int threshold, len, n, pre[MAX_N], dp[MAX_N][MAX_N][MAX_N], units[MAX_N];
char str[MAX_N];
int main()
{
scanf("%s%d", str + 1, &threshold), len = strlen(str + 1);
int last_pos = 0, ones = 0;
for (int i = 1; i <= len; i++)
ones += str[i] == '1';
for (int i = 1; i <= len + 1; i++)
if (str[i] != '1')
units[++n] = i - last_pos - 1, last_pos = i;
for (int i = 1; i <= n; i++)
pre[i] = pre[i - 1] + units[i];
dp[0][0][0] = 1, threshold = min(threshold, ones);
for (int i = 0; i < n; i++)
for (int j = pre[i]; j <= pre[n]; j++)
for (int k = 0; k <= threshold; k++)
if (dp[i][j][k])
{
for (int g = max(j, pre[i + 1]); g <= pre[n]; g++)
if (k + g - j - units[i + 1] <= threshold)
{
if (i + 1 == n && g - j > units[i + 1])
break;
int cost = g - j <= units[i + 1] ? 0 : g - j - units[i + 1];
dp[i + 1][g][k + cost] = (0LL + dp[i + 1][g][k + cost] + dp[i][j][k]) % mod;
}
}
int ans = 0;
for (int i = 0; i <= threshold; i++)
ans = (0LL + ans + dp[n][ones][i]) % mod;
printf("%d\n", ans);
return 0;
}
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 330, mod = 998244353;
int threshold, len, n, pre[MAX_N], dp[MAX_N][MAX_N][MAX_N], units[MAX_N];
char str[MAX_N];
int main()
{
scanf("%s%d", str + 1, &threshold), len = strlen(str + 1);
int last_pos = 0, ones = 0;
for (int i = 1; i <= len; i++)
ones += str[i] == '1';
for (int i = 1; i <= len + 1; i++)
if (str[i] != '1')
units[++n] = i - last_pos - 1, last_pos = i;
for (int i = 1; i <= n; i++)
pre[i] = pre[i - 1] + units[i];
dp[0][0][0] = 1, threshold = min(threshold, ones);
for (int i = 0; i < n; i++)
for (int j = pre[i]; j <= pre[n]; j++)
for (int k = 0; k <= threshold; k++)
if (dp[i][j][k])
{
for (int g = max(j, pre[i + 1]); g <= pre[n]; g++)
if (k + g - j - units[i + 1] <= threshold)
{
if (i + 1 == n && g - j > units[i + 1])
break;
int cost = g - j <= units[i + 1] ? 0 : g - j - units[i + 1];
dp[i + 1][g][k + cost] = (0LL + dp[i + 1][g][k + cost] + dp[i][j][k]) % mod;
}
}
int ans = 0;
for (int i = 0; i <= threshold; i++)
ans = (0LL + ans + dp[n][ones][i]) % mod;
printf("%d\n", ans);
return 0;
}
D – Secret Passage
大概是能想出来的,但是写起来有点麻烦。 先定下终串的长度 \(|T|\),然后在前 \(|S| – |T|\) 个字符中选一半留下、一半抛弃(前两个中有一个必须要选,而且必须要合法),然后再找一个 \(|T| – \frac{|S| – |T|}{2}\) 的后缀当作子序列插到 \(T\) 里。然后求本质不同的串。 那么,我们先求一个方案数:有 \(j\) 个额外的 \(0\) 和 \(k\) 个额外的 \(1\),然后有 \(i\) 后缀作子序列。求完这个之后,我们还需要判合法性。 判断合法性,我们可以维护一个 vis 数组来记录前 \(i\) 个字符被抽走了 \(j\) 个 \(0\)、\(k\) 个 \(1\) 之后还剩多少个字符给剩下的 \(|S|-(i-j-k)\) 的前缀。如果有余(指大于等于 0),那么就是合法的。
const int MAX_N = 330, mod = 998244353;
int n, dp[MAX_N][MAX_N][MAX_N], vis[MAX_N][MAX_N][MAX_N];
bool verdict[MAX_N][MAX_N][MAX_N];
scanf("%s", str + 1), n = strlen(str + 1);
for (int i = n; i >= 1; i--)
for (int j = 0; j + (n - i) <= n - 1; j++)
for (int k = 0; j + k + (n - i) <= n - 1; k++)
dp[i - 1][j][k] = (0LL + dp[i - 1][j][k] + dp[i][j][k]) % mod;
dp[i][j][k + 1] = (0LL + dp[i][j][k + 1] + dp[i][j][k]) % mod;
dp[i - 1][j][k] = (0LL + dp[i - 1][j][k] + dp[i][j][k]) % mod;
dp[i][j + 1][k] = (0LL + dp[i][j + 1][k] + dp[i][j][k]) % mod;
memset(vis, -1, sizeof(vis)), vis[0][0][0] = 0;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= (i >> 1); j++)
for (int k = 0; j + k <= (i >> 1); k++)
if (i + 1 <= n && c != 0)
vis[i + 1][j + 1][k] = max(vis[i + 1][j + 1][k], c - 1);
vis[i + 1][j][k + 1] = max(vis[i + 1][j][k + 1], c - 1);
if (str[i + 1] == '0' || str[i + 2] == '0')
vis[i + 2][j + 1][k] = max(vis[i + 2][j + 1][k], c);
if (str[i + 1] == '1' || str[i + 2] == '1')
vis[i + 2][j][k + 1] = max(vis[i + 2][j][k + 1], c);
vis[i + 2][j][k] = max(vis[i + 2][j][k], c + 1);
for (int i = 0; i <= n; i++)
for (int j = n; j >= 0; j--)
for (int k = n; k >= 0; k--)
verdict[i][j][k] = vis[i][j][k] != -1;
verdict[i][j][k] |= verdict[i - 1][j][k];
verdict[i][j][k] |= verdict[i][j + 1][k] || verdict[i][j][k + 1];
for (int i = 0; i <= n; i++)
for (int j = 0; j + (n - i) <= n; j++)
for (int k = 0; j + k + (n - i) <= n; k++)
if (dp[i][j][k] && (n - i) + j + k != 0 && verdict[i][j][k])
ans = (0LL + ans + dp[i][j][k]) % mod;
// D.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 330, mod = 998244353;
int n, dp[MAX_N][MAX_N][MAX_N], vis[MAX_N][MAX_N][MAX_N];
bool verdict[MAX_N][MAX_N][MAX_N];
char str[MAX_N];
int main()
{
scanf("%s", str + 1), n = strlen(str + 1);
dp[n][0][0] = 1;
for (int i = n; i >= 1; i--)
for (int j = 0; j + (n - i) <= n - 1; j++)
for (int k = 0; j + k + (n - i) <= n - 1; k++)
if (str[i] == '0')
{
dp[i - 1][j][k] = (0LL + dp[i - 1][j][k] + dp[i][j][k]) % mod;
dp[i][j][k + 1] = (0LL + dp[i][j][k + 1] + dp[i][j][k]) % mod;
}
else
{
dp[i - 1][j][k] = (0LL + dp[i - 1][j][k] + dp[i][j][k]) % mod;
dp[i][j + 1][k] = (0LL + dp[i][j + 1][k] + dp[i][j][k]) % mod;
}
memset(vis, -1, sizeof(vis)), vis[0][0][0] = 0;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= (i >> 1); j++)
for (int k = 0; j + k <= (i >> 1); k++)
if (vis[i][j][k] != -1)
{
int c = vis[i][j][k];
if (i + 1 <= n && c != 0)
{
if (str[i + 1] == '0')
vis[i + 1][j + 1][k] = max(vis[i + 1][j + 1][k], c - 1);
if (str[i + 1] == '1')
vis[i + 1][j][k + 1] = max(vis[i + 1][j][k + 1], c - 1);
}
if (i + 2 <= n)
{
if (str[i + 1] == '0' || str[i + 2] == '0')
vis[i + 2][j + 1][k] = max(vis[i + 2][j + 1][k], c);
if (str[i + 1] == '1' || str[i + 2] == '1')
vis[i + 2][j][k + 1] = max(vis[i + 2][j][k + 1], c);
vis[i + 2][j][k] = max(vis[i + 2][j][k], c + 1);
}
}
for (int i = 0; i <= n; i++)
for (int j = n; j >= 0; j--)
for (int k = n; k >= 0; k--)
{
verdict[i][j][k] = vis[i][j][k] != -1;
if (i > 0)
verdict[i][j][k] |= verdict[i - 1][j][k];
verdict[i][j][k] |= verdict[i][j + 1][k] || verdict[i][j][k + 1];
}
int ans = 0;
for (int i = 0; i <= n; i++)
for (int j = 0; j + (n - i) <= n; j++)
for (int k = 0; j + k + (n - i) <= n; k++)
if (dp[i][j][k] && (n - i) + j + k != 0 && verdict[i][j][k])
ans = (0LL + ans + dp[i][j][k]) % mod;
printf("%d\n", ans);
return 0;
}
// D.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 330, mod = 998244353;
int n, dp[MAX_N][MAX_N][MAX_N], vis[MAX_N][MAX_N][MAX_N];
bool verdict[MAX_N][MAX_N][MAX_N];
char str[MAX_N];
int main()
{
scanf("%s", str + 1), n = strlen(str + 1);
dp[n][0][0] = 1;
for (int i = n; i >= 1; i--)
for (int j = 0; j + (n - i) <= n - 1; j++)
for (int k = 0; j + k + (n - i) <= n - 1; k++)
if (str[i] == '0')
{
dp[i - 1][j][k] = (0LL + dp[i - 1][j][k] + dp[i][j][k]) % mod;
dp[i][j][k + 1] = (0LL + dp[i][j][k + 1] + dp[i][j][k]) % mod;
}
else
{
dp[i - 1][j][k] = (0LL + dp[i - 1][j][k] + dp[i][j][k]) % mod;
dp[i][j + 1][k] = (0LL + dp[i][j + 1][k] + dp[i][j][k]) % mod;
}
memset(vis, -1, sizeof(vis)), vis[0][0][0] = 0;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= (i >> 1); j++)
for (int k = 0; j + k <= (i >> 1); k++)
if (vis[i][j][k] != -1)
{
int c = vis[i][j][k];
if (i + 1 <= n && c != 0)
{
if (str[i + 1] == '0')
vis[i + 1][j + 1][k] = max(vis[i + 1][j + 1][k], c - 1);
if (str[i + 1] == '1')
vis[i + 1][j][k + 1] = max(vis[i + 1][j][k + 1], c - 1);
}
if (i + 2 <= n)
{
if (str[i + 1] == '0' || str[i + 2] == '0')
vis[i + 2][j + 1][k] = max(vis[i + 2][j + 1][k], c);
if (str[i + 1] == '1' || str[i + 2] == '1')
vis[i + 2][j][k + 1] = max(vis[i + 2][j][k + 1], c);
vis[i + 2][j][k] = max(vis[i + 2][j][k], c + 1);
}
}
for (int i = 0; i <= n; i++)
for (int j = n; j >= 0; j--)
for (int k = n; k >= 0; k--)
{
verdict[i][j][k] = vis[i][j][k] != -1;
if (i > 0)
verdict[i][j][k] |= verdict[i - 1][j][k];
verdict[i][j][k] |= verdict[i][j + 1][k] || verdict[i][j][k + 1];
}
int ans = 0;
for (int i = 0; i <= n; i++)
for (int j = 0; j + (n - i) <= n; j++)
for (int k = 0; j + k + (n - i) <= n; k++)
if (dp[i][j][k] && (n - i) + j + k != 0 && verdict[i][j][k])
ans = (0LL + ans + dp[i][j][k]) % mod;
printf("%d\n", ans);
return 0;
}
E – Permutation Cover
这个题很好啊。
我们首先要知道,有解需要满足 \(2\min\{a_i\} \geq \max\{a_i\}\),考虑在出现最大值的分界点会出现三个相同的数,这样就 GG 了。
如果有解,我们可以先考虑构造第一个前缀出来,这样我们后面就可以贪心的去拼接了。每次我们枚举拼在上一个段后面的段长,然后找字典序最小的。如果我们在 \(a_i\) 中先扣除掉这个前缀的频数,然后再来判:如果满足 \(2\min\{a_i\} \geq \max\{a_i\}\),那我们可以先直接 1、2、3、4 这样去搞,这样字典序最小且对 \(a_i\) 只有 1 的扣除。这样下去会出现 \(2\min\{a_i\} + 1 = \max\{a_i\}\) 的情况,然而这种情况下也是有解法的:我们可以考虑让 \(a_i\) 最大的 \(i\) 排在让 \(a_j\) 最小的 \(j\) 前面,然后再和剩下的那些项去归并。
int n, sum, ai[MAX_N], res[MAX_N], candid[MAX_N], pos[MAX_N];
int upper, lower, sa[MAX_N], sb[MAX_N], ans[MAX_N], ansptr;
bool compare(const int &x, const int &y)
if ((ai[x] == lower) == (ai[y] == lower))
return (ai[x] == lower) < (ai[y] == lower);
for (int i = 1; i <= len; i++)
int min_val = *min_element(ai + 1, ai + 1 + n), max_val = *max_element(ai + 1, ai + 1 + n);
if ((min_val << 1) >= max_val)
for (int i = 1; i <= len; i++)
sort(res + 1, res + 1 + len), found = true;
else if (((min_val << 1) | 1) == max_val)
upper = max_val, lower = min_val;
int ptra = 1, ptrb = 1, la = 0, lb = 0, ptr = 0;
for (int i = 1; i <= len; i++)
if (ai[pos[i]] == min_val || ai[pos[i]] == max_val)
sort(sa + 1, sa + 1 + la, compare), sort(sb + 1, sb + 1 + lb);
while (ptra <= la && ptrb <= lb)
for (int i = len + 1; i <= n; i++)
if (ai[pos[i]] == min_val)
found |= (ai[sa[1]] == max_val);
for (int i = 1; i <= len; i++)
bool lexicographicalCompare(int *s1, int *s2)
while (s1[ptr] == s2[ptr])
return s1[ptr] < s2[ptr];
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]), sum += ai[i], pos[i] = i;
if (((*min_element(ai + 1, ai + 1 + n)) << 1) < *max_element(ai + 1, ai + 1 + n))
for (int i = 1; i <= n; i++)
ans[++ansptr] = res[i], ai[res[i]]--, pos[i] = res[i];
memset(candid, 0, sizeof(candid)), candid[1] = n + 1;
for (int i = 1; i <= n; i++)
if (res[1] != 0 && lexicographicalCompare(res, candid))
for (int j = 1; j <= i; j++)
for (int i = 1; i + len <= n; i++)
for (int i = 1; i <= len; i++)
ans[++ansptr] = pos[n - len + i] = candid[i], ai[candid[i]]--;
for (int i = 1; i <= ansptr; i++)
// E.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1050;
int n, sum, ai[MAX_N], res[MAX_N], candid[MAX_N], pos[MAX_N];
int upper, lower, sa[MAX_N], sb[MAX_N], ans[MAX_N], ansptr;
bool compare(const int &x, const int &y)
{
if ((ai[x] == lower) == (ai[y] == lower))
return x < y;
else
return (ai[x] == lower) < (ai[y] == lower);
}
void solve(int len)
{
bool found = false;
for (int i = 1; i <= len; i++)
ai[pos[i]]--;
int min_val = *min_element(ai + 1, ai + 1 + n), max_val = *max_element(ai + 1, ai + 1 + n);
if ((min_val << 1) >= max_val)
{
for (int i = 1; i <= len; i++)
res[i] = pos[i];
sort(res + 1, res + 1 + len), found = true;
}
else if (((min_val << 1) | 1) == max_val)
{
upper = max_val, lower = min_val;
int ptra = 1, ptrb = 1, la = 0, lb = 0, ptr = 0;
for (int i = 1; i <= len; i++)
if (ai[pos[i]] == min_val || ai[pos[i]] == max_val)
sa[++la] = pos[i];
else
sb[++lb] = pos[i];
sort(sa + 1, sa + 1 + la, compare), sort(sb + 1, sb + 1 + lb);
// merge;
while (ptra <= la && ptrb <= lb)
if (sa[ptra] < sb[ptrb])
res[++ptr] = sa[ptra++];
else
res[++ptr] = sb[ptrb++];
while (ptra <= la)
res[++ptr] = sa[ptra++];
while (ptrb <= lb)
res[++ptr] = sb[ptrb++];
found = true;
for (int i = len + 1; i <= n; i++)
if (ai[pos[i]] == min_val)
found = false;
found |= (ai[sa[1]] == max_val);
}
for (int i = 1; i <= len; i++)
ai[pos[i]]++;
if (!found)
res[1] = 0;
}
bool lexicographicalCompare(int *s1, int *s2)
{
int ptr = 1;
while (s1[ptr] == s2[ptr])
ptr++;
return s1[ptr] < s2[ptr];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]), sum += ai[i], pos[i] = i;
if (((*min_element(ai + 1, ai + 1 + n)) << 1) < *max_element(ai + 1, ai + 1 + n))
puts("-1"), exit(0);
solve(n);
for (int i = 1; i <= n; i++)
ans[++ansptr] = res[i], ai[res[i]]--, pos[i] = res[i];
while (ansptr < sum)
{
memset(candid, 0, sizeof(candid)), candid[1] = n + 1;
int len = 0;
for (int i = 1; i <= n; i++)
{
solve(i);
if (res[1] != 0 && lexicographicalCompare(res, candid))
{
len = i;
for (int j = 1; j <= i; j++)
candid[j] = res[j];
}
}
for (int i = 1; i + len <= n; i++)
pos[i] = pos[i + len];
for (int i = 1; i <= len; i++)
ans[++ansptr] = pos[n - len + i] = candid[i], ai[candid[i]]--;
}
for (int i = 1; i <= ansptr; i++)
printf("%d ", ans[i]);
puts("");
return 0;
}
// E.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1050;
int n, sum, ai[MAX_N], res[MAX_N], candid[MAX_N], pos[MAX_N];
int upper, lower, sa[MAX_N], sb[MAX_N], ans[MAX_N], ansptr;
bool compare(const int &x, const int &y)
{
if ((ai[x] == lower) == (ai[y] == lower))
return x < y;
else
return (ai[x] == lower) < (ai[y] == lower);
}
void solve(int len)
{
bool found = false;
for (int i = 1; i <= len; i++)
ai[pos[i]]--;
int min_val = *min_element(ai + 1, ai + 1 + n), max_val = *max_element(ai + 1, ai + 1 + n);
if ((min_val << 1) >= max_val)
{
for (int i = 1; i <= len; i++)
res[i] = pos[i];
sort(res + 1, res + 1 + len), found = true;
}
else if (((min_val << 1) | 1) == max_val)
{
upper = max_val, lower = min_val;
int ptra = 1, ptrb = 1, la = 0, lb = 0, ptr = 0;
for (int i = 1; i <= len; i++)
if (ai[pos[i]] == min_val || ai[pos[i]] == max_val)
sa[++la] = pos[i];
else
sb[++lb] = pos[i];
sort(sa + 1, sa + 1 + la, compare), sort(sb + 1, sb + 1 + lb);
// merge;
while (ptra <= la && ptrb <= lb)
if (sa[ptra] < sb[ptrb])
res[++ptr] = sa[ptra++];
else
res[++ptr] = sb[ptrb++];
while (ptra <= la)
res[++ptr] = sa[ptra++];
while (ptrb <= lb)
res[++ptr] = sb[ptrb++];
found = true;
for (int i = len + 1; i <= n; i++)
if (ai[pos[i]] == min_val)
found = false;
found |= (ai[sa[1]] == max_val);
}
for (int i = 1; i <= len; i++)
ai[pos[i]]++;
if (!found)
res[1] = 0;
}
bool lexicographicalCompare(int *s1, int *s2)
{
int ptr = 1;
while (s1[ptr] == s2[ptr])
ptr++;
return s1[ptr] < s2[ptr];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]), sum += ai[i], pos[i] = i;
if (((*min_element(ai + 1, ai + 1 + n)) << 1) < *max_element(ai + 1, ai + 1 + n))
puts("-1"), exit(0);
solve(n);
for (int i = 1; i <= n; i++)
ans[++ansptr] = res[i], ai[res[i]]--, pos[i] = res[i];
while (ansptr < sum)
{
memset(candid, 0, sizeof(candid)), candid[1] = n + 1;
int len = 0;
for (int i = 1; i <= n; i++)
{
solve(i);
if (res[1] != 0 && lexicographicalCompare(res, candid))
{
len = i;
for (int j = 1; j <= i; j++)
candid[j] = res[j];
}
}
for (int i = 1; i + len <= n; i++)
pos[i] = pos[i + len];
for (int i = 1; i <= len; i++)
ans[++ansptr] = pos[n - len + i] = candid[i], ai[candid[i]]--;
}
for (int i = 1; i <= ansptr; i++)
printf("%d ", ans[i]);
puts("");
return 0;
}