传送门: https://codeforces.ml/contest/1469/problem/D
题意
一
段
序
列
a
1
.
.
.
a
n
,
a
i
=
i
,
最
多
n
+
5
次
操
作
后
,
使
序
列
变
为
n
−
1
个
1
和
1
个
2
。
一段序列a_1...a_n,a_i=i,最多n+5次操作后,使序列变为n-1个1和1个2。
一段序列a1...an,ai=i,最多n+5次操作后,使序列变为n−1个1和1个2。
这
个
操
作
为
,
先
选
择
两
个
数
x
和
y
,
然
后
使
a
x
=
⌈
a
x
a
y
⌉
.
这个操作为,先选择两个数x和y,然后使ax=\left \lceil \frac{ax}{ay} \right \rceil.
这个操作为,先选择两个数x和y,然后使ax=⌈ayax⌉.
思路
辗 转 根 号 , 这 个 操 作 在 n = 2 e 5 时 , 最 多 5 ∗ 2 次 , 每 次 ( n , n ) 需 要 两 次 。 \red{辗转根号},这个操作在n=2e5时,最多5*2次,每次(n,\sqrt n)需要两次。 辗转根号,这个操作在n=2e5时,最多5∗2次,每次(n,n)需要两次。
对 于 每 个 区 间 ( n , n ) , 只 需 要 选 择 ( i , i + 1 ) 操 作 一 次 就 变 成 1 了 。 对于每个区间(\sqrt n, n),只需要选择(i,i+1)操作一次就变成1了。 对于每个区间(n,n),只需要选择(i,i+1)操作一次就变成1了。
总 次 数 为 n − 7 + 5 ∗ 2 = n + 3 次 。 总次数为n-7+5*2=n+3次。 总次数为n−7+5∗2=n+3次。
Code
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const ll mod = 1e9 + 7;
// const double eps = 1e-6;
// const double PI = acos(-1);
// const double R = 0.57721566490153286060651209;
void solve()
{
int _; cin >> _;
while(_--) {
int n; cin >> n;
vector<pair<int, int> > v, x(20);
vector<int> a(10);
int t = n;
int k = 0;
while(t > 2) {
a[++k] = t;
t = (int) (ceil(sqrt(t)));
}
t = k;
for(int i = 3;i <= n; i++) {
if(i == a[t]) {
x[t * 2] = {i, (int)(ceil(sqrt(i)))};
x[t * 2 - 1] = {i, (int)(ceil(sqrt(i)))};
t--;
}
else v.push_back({i, i + 1});
}
cout << v.size() + k * 2 << endl;
for(auto i : v) {
cout << i.first << " " << i.second << endl;
}
for(int i = 1;i <= 2 * k; i++) {
cout << x[i].first << " " << x[i].second << endl;
}
}
}
signed main() {
solve();
}