C. Numbers on Whiteboard
题意:
给你一个排列1-n,每次可以选择两个数,(
⌈
a
+
b
2
⌉
\lceil \frac{a+b}{2} \rceil
⌈2a+b⌉)进行向上取整,之后删除a,b. 最后添加
⌈
a
+
b
2
⌉
\lceil \frac{a+b}{2} \rceil
⌈2a+b⌉。
求进行n-1次操作后,的最小数。
并输出每次的操作。
思路:
- 有件事肯定可以知道,最小肯定是2.(所以直接输出即可。)
思路有很多,
2. 有一个红名大佬,直接大大合并。(最大和次大合并,会把次大消化,所以对答案不会有影响)
3. 我是隔着合并
AC(1大佬的%%%%%%%%)
#include <iostream>
#include <queue>
using namespace std;
priority_queue<int>q;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int tt;cin>>tt;
while(tt--){
while(!q.empty())q.pop();
int n,a,b;cin>>n;
for(int i=1; i<=n; i++)q.push(i);
cout<<2<<endl;
for(int i=1; i<n; i++){
a=q.top();q.pop();
b=q.top();q.pop();
cout<<a<<' '<<b<<endl;
q.push((a+b+1)/2);
}
}
return 0;
}
AC(2)
#include <iostream>
#include <vector>
using namespace std;
const int maxn=2e5+10;
int vis[maxn];
int main()
{
ios::sync_with_stdio(0);
int tt;cin>>tt;
while(tt--){
int n;cin>>n;
cout<<2<<endl;
if(n==2){
cout<<1<<' '<<2<<endl;
continue;
}
for(int i=1; i<=n; i++)vis[i]=1;
int tot=0;
for(int i=n; ; i--){
if(vis[i]){
int a=i;
int b=i-2;
cout<<a<<' '<<b<<endl;
tot++;
if(tot>=n-1)break;
int c=(a+b)/2;
if(vis[c]){
cout<<c<<' '<<c<<endl;
tot++;
}else vis[c]++;
if(tot>=n-1)break;
vis[i]--;
vis[b]--;
}
}
}
return 0;
}