第十八届浙大城市学院程序设计竞赛(同步赛)D
第十八届浙大城市学院程序设计竞赛(同步赛)D
大意
略。。
思路
。。有点尴尬,下次这种题一定画图。。
画图容易发现,对于 \(n-ary tree\) ,每棵子树的倒数第二个节点的标号除以 \(n\) 一定是父亲节点的标号。。
严格的证明:
不妨设节点 \(A\) 在第 \(i\) 层,位于本层第 \(j\) 个。
由题得知每层的节点数是等比的,不妨设为 \(k\)
所以节点 \(A\) 的标号为 \(\dfrac{k^{i-1}-1}{k-1}+j\)
考虑节点 \(B\) 为 \(A\) 的子树中倒数第二个节点
可以得到节点 \(B\) 的标号
\(\dfrac{k^i-1}{k-1}+j*k-1=\dfrac{k^i-1-k+1}{k-1}+j*k=k*(\dfrac{k^{i-1}-1}{k-1}+j)\)
即为上面画图看出的结论。
然后,如果标号减一可以被 \(k\) 整除,说明,标号代表某棵子树的最后一个节点,那么减一,否则加上 \(k-2\)
最后除以 \(k\) 就得到了父亲节点的标号。
代码
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)
const int mod = 1e9+7;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
int t;
ll n, x, y;
void sol(ll n, ll x, ll y) {
while(x != y) {
if(x < y) swap(x, y);
if(x % n == 1) --x;
else x += n-2;
x /= n;
}
cout << x << endl;
}
int main() {
cin >> t;
while(t--) {
cin >> n >> x >> y;
if(n == 1) cout << min(x, y) << endl;
else sol(n, x, y);
}
return 0;
}