[CF1469D] Ceil Divisions - 构造
Description
给定一个长度为 n 的序列 ai=i,每次可以选择两个数 x,y,将 ax 改为 ceil(ax/ay),在 n+5 步操作内将 a 修改为 n-1 个 1 和 1 个 2 构成的序列。
Solution
如果是 n+25,我们显然会考虑先用 i 除以 n 做到 1,1,1,...,2,n 的情况,然后不断除即可
现在要求 n+5,我们考虑一下根号,在找到第一个小于 sqrt(n) 的数的时候,把当前的最大值 n 做掉(用 n 除以 sqrt(n)),更新集合然后继续
具体地,我们用一个 set 维护,每次取出当前最大值 y 和次大值 x,如果 (x^2 > y),那么直接将次大值做成 1 了,删掉就好;否则,用次大值去除最大值,除出来的元素塞回去
执行到 y=2,x=1 时停止
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int t, n, a[N];
signed main()
{
ios::sync_with_stdio(false);
cin >> t;
while (t--)
{
cin >> n;
multiset<pair<int, int>> s;
for (int i = 1; i <= n; i++)
s.insert({i, i});
vector<pair<int, int>> ans;
while (true)
{
pair<int, int> y = *s.rbegin(), x = *(++s.rbegin()), z = *(++(++s.rbegin()));
// cerr << x.first << " " << y.first << endl;
if (y.first == 2 && x.first == 1)
break;
if (x.first * x.first > y.first && z.first != 1)
{
ans.push_back({x.second, y.second});
s.erase(x);
x.first = 1;
s.insert(x);
}
else
{
ans.push_back({y.second, x.second});
s.erase(y);
y.first = (y.first + x.first - 1) / x.first;
s.insert(y);
}
}
cout << ans.size() << endl;
for (auto [x, y] : ans)
cout << x << " " << y << endl;
}
}