A Array

题意:给定长度为 nn 的序列 {an}\{a_n\}。现构造一个序列 {bm}\{b_m\},令 {c}\{c\}{bm}\{b_m\} 序列的无穷拼接,要求 {c}\{c\} 中每连续 aia_i 个数字就得出现一次 ii。要求 {bm}\{b_m\} 序列长度 m1×106m\leq 1\times 10^6

解法:设最终长度为 MM。首先注意到,对于每个数字,最少填放次数为 Mai\left \lceil \dfrac{M}{a_i}\right \rceil,因而理论上满足 i=1nMaiM\displaystyle \sum_{i=1}^n \left \lceil \dfrac{M}{a_i}\right \rceil \leq M 即可保证有解,可推出即 i=1n1ai1\displaystyle \sum_{i=1}^n \dfrac{1}{a_i}\leq 1。此题条件更为苛刻:i=1n1ai12\displaystyle \sum_{i=1}^n \dfrac{1}{a_i}\leq \dfrac{1}{2},暗示可能需要对 aia_i 进行适当的缩小,至多可以缩小到原来的一半。

因而可以考虑这样的构造:令 M=2kM=2^ki[1,n]\forall i \in [1,n]ai2ja_i' \leftarrow 2^j,其中 2j2^j 为小于等于 aia_i 的最大值。这样 i=1n1ai1\displaystyle \sum_{i=1}^n \dfrac{1}{a_i'}\leq 1。同时,由于 aiMa_i'|M,因而不会出现多个数字都要填在同一处导致某些数字需要出现的更多以满足条件,从小到大的对 aia_i' 进行填放。即可。实际操作中可取 M=219M=2^{19}

#include <bits/stdc++.h>
using namespace std;
const int N = 100000, M = 1 << 19;
pair<int, int> a[N + 5];
int ans[M + 5];
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n;i++)
	{
		scanf("%d", &a[i].first);
		a[i].second = i;
		for (int j = 20; j >= 0;j--)
			if (a[i].first >> j & 1)
			{
				a[i].first = 1 << j;
				break;
			}
	}
	sort(a + 1, a + n + 1);
	int now = 1;
	for (int i = 1; i <= n; i++)
	{
		for (int j = now; j <= M; j += a[i].first)
			ans[j] = a[i].second;
		while (ans[now])
			now++;
	}
	printf("%d\n", M);
	for (int i = 1; i <= M;i++)
		printf("%d ", !ans[i] ? 1 : ans[i]);
	return 0;
}