HDU 6098 Inversion (序列变换)
Description
给出数组A,下标从\(1\)开始,求数组B
\[B_i=\max_{i \nmid j} A_j, i \leqslant 2
\]
Input
第一行给出用例组数\(T\),对于每组用例,第一行给出A数组的长度,第二行给出\(n\)个数表示数组A的元素。\(T \leqslant 20\),\(2 \leqslant n \leqslant 10^5\),\(1 \leqslant A_i \leqslant 10^9\)。
Output
对于每组用例,输出\(n-1\)个整数,分别表示\(B_2\),\(B_3\),\(\cdots\),\(B_n\)。
Sample Input
2
4
1 2 3 4
4
1 4 2 3
Sample Output
3 4 3
2 4 4
Solution
典型的序列变换问题,数据规模是\(10^5\),显然最后复杂度为\(O(nlogn)\),这道题又涉及到整除,显然\(O(logn)\)就要来自于因子的个数。
设A数组中最大的数为\(A_k\),对于\(k\),它的因子只有\(\log n\)个,其余的\(n- \log n\)个数都不能整除\(k\),也就是B数组中的\(n-\log n\)个不能整除\(k\)的下标对应的值就是\(A_k\),对于\(k\)的\(\log n\)个因子,每个因子扫描一遍A数组寻找满足条件的最大值即可。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
typedef pair<int, int> pii;
pii a[N];
int b[N];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i].first), a[i].second = i;
sort(a + 1, a + n + 1);
for (int i = 2; i <= n; i++)
for (int j = n; j >= 1; j--)
if (a[j].second % i != 0)
{
b[i] = a[j].first;
break;
}
for (int i = 2; i < n; i++) printf("%d ", b[i]);
printf("%d\n", b[n]);
}
return 0;
}