Codeforce D. Ceil Divisions (構造+思維)
阿新 • • 發佈:2021-07-21
題意:
給你一個長度為 \(n\) 的序列 \(a\) 滿足 \(a_i=i\)
你每次可以進行一次如下操作:
- 選擇兩個數 \(a_x,a_y\),將 \(a_x\) 修改為 \(\lceil\frac{a_x}{a_y}\rceil\)
你需要在 \(n+5\) 步之內將這個序列 \(a\) 修改為 \(n-1\) 個 1 和 1 個 2 的序列。
輸出方案,即每一步操作的 \(x,y\)。
注意:你不需要最小化步數。
思路:
我們可以很明顯看出來這樣一條性質:
- 如果進行\(\dfrac{n}{n-1}\)操作,向上取整會得到 2 。
- 如果進行 \(\dfrac{n}{n+1}\)
很明顯操作2更能減少步數,所以我們儘量的先參用操作2,這樣我們就可以通過\((n-3)\)步將陣列中\(3到(n-1)\) 變成1 還剩下2和n,如果我們一直除2的話,肯定是不行的,所以我們需要再過程中將n簡化,所以我們就想到了\(\sqrt{n}\),這樣我們可以盡最大努力簡化n,而為了不影響\(3到(n-1)\)化1的過程,所以我們就需要在這個過程中,遇到一個接近\(\sqrt{n}\)的才把n簡化.這樣步數就不會超了.
// Problem: D. Ceil Divisions // Contest: Codeforces - Educational Codeforces Round 101 (Rated for Div. 2) // URL: https://codeforces.com/contest/1469/problem/D // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; typedef unsigned long long ull; #define x first #define y second #define sf scanf #define pf printf #define PI acos(-1) #define inf 0x3f3f3f3f #define lowbit(x) ((-x)&x) #define mem(a,x) memset(a,x,sizeof(a)) #define rep(i,n) for(int i=0;i<(n);++i) #define repi(i,a,b) for(int i=int(a);i<=(b);++i) #define repr(i,b,a) for(int i=int(b);i>=(a);--i) #define debug(x) cout << #x << ": " << x << endl; const int MOD = 998244353; const int mod = 1e9 + 7; const int maxn = 2e5 + 10; const int dx[] = {0, 1, -1, 0, 0}; const int dy[] = {0, 0, 0, 1, -1}; const int dz[] = {1, -1, 0, 0, 0, 0 }; int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; ll n; ll a[maxn],b[maxn],c[maxn]; void solve() { cin>>n; ll cnt=0; ll ans=n; for(int i=n-1;i>2;i--){ if(ans/i>=i){ if(ans%i==0){ ans=ans/i; }else ans=ans/i+1; b[++cnt]=n; c[cnt]=i; } b[++cnt]=i; c[cnt]=n; } while(ans>=2) { if(ans%2==0) ans/=2; else ans=ans/2+1; b[++cnt]=n; c[cnt]=2; } cout<<cnt<<endl; for(int i=1;i<=cnt;i++){ cout<<b[i]<<" "<<c[i]<<endl; } } int main() { ll t = 1; scanf("%lld",&t); while(t--) { solve(); } return 0; }