题解:P14145 荒谬
P14145 荒谬
声明感谢同校大佬 zwm ,没有他的点拨就没有这篇题解
有够荒谬的,黄题就一个递归没想到,导致4个要打noip的人原地爆炸
::::info[题目描述]
给定
点对
输入格式
一行一个正整数
输出格式
第一行一个整数
之后
输入输出样例 #1
输入 #1
3
输出 #1
2
1 2
2 3
说明/提示
样例解释
样例中唯一距离为
数据范围
:::
这个很明显是一个很好的提示,提示了这个图的形状
当然,我数学注意力不强
或我们可以自行举例构造
STEP 1
题目要求我们尽可能多的找距离为二的点对,这时候我们很容易想到菊花图可以出现很多距离为 一 的点对 进一步想,把它对半分不就可以得到很多点对满足要求了吗? 如图所示:
好丑
预计得分 : 20
STEP 2
其实不用交代码,不用仔细想就会发现我们的算法增长的速度有亿点慢,这要如何解决呢?
我们容易想到,再加几个类似的结构就好了!
so ……
对题目使用递归吧!(
运用递归我们就可以得到这么一个东西,其中红的框框住的点和红点连接,其中黄的框框住的点和黄点连接
特别注意,红黄的箭头的意思是与红黄点有边,并不是说边的方向是这么连的,方向和其他的方向相一致,具体方向和细节处理请读者自行思考
最后你就会发现,这个构图法和那个神秘的公式有千丝万缕的联系,大家可以计算一下!
并不是因为我没算出来
代码时间
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int>> G;
void solve(int l, int r){
if(l >= r) return;
int mid = l + r >> 1;
for(int i = l; i < mid; ++i) G.push_back({i, mid});
for(int i = mid + 1; i <= r; ++i) G.push_back({mid, i});
solve(l, mid-1);
solve(mid+1, r);
}
int main(){
int n;
cin >> n;
solve(1, n);
cout << G.size() << endl;
for(auto e: G) printf("%d %d\n", e.first, e.second);
return 0;
//这是那个同校大佬的代码,本蒟蒻马蜂有点丑陋
}
各位大佬喜欢记得点个赞!题解新手,有错请指出!