第十八届浙大城市学院程序设计竞赛(同步赛)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;
}
posted @ 2021-03-30 14:12  ullio  阅读(52)  评论(0编辑  收藏  举报