蓝桥杯真题 - 子树的大小 - 题解

题目链接:https://www.lanqiao.cn/problems/3526/learning/

个人评价:难度 2 星(满星:5)
前置知识:无


整体思路

  • 整体将节点编号 − 1 -1 1,通过找规律可以发现,节点 i i i 下一层最左边的节点编号是 i m + 1 im+1 im+1,最右边的节点编号是 i m + m im+m im+m
  • l , r l,r l,r 分别标记当前层子树的最小节点编号与最大节点编号,每次让最左边的节点往下一层的最左子节点走一步(即从 l l l l m + 1 lm+1 lm+1),让最右边的节点往下一层的最右子节点走一步(即从 r r r r m + 1 rm+1 rm+1),则每层属于节点 k k k 子树范围内的节点编号就是 [ l , r ] [l,r] [l,r],子节点个数是 r − l + 1 r-l+1 rl+1
  • l , r l,r l,r 初始值为 k k k(减一后),一直往下一层走,直到 l , r l,r l,r 超过 n n n,每走一层都加上这一层的节点数,就是最终答案。

过题代码

#include
using namespace std;

typedef long long LL;
const LL MOD = 100 + 100;
int T;
LL n, m, k, l, r, ans;

int main() {
#ifdef ExRoc
    freopen("test.txt", "r", stdin);
#endif // ExRoc
    ios::sync_with_stdio(false);

    cin >> T;
    while (T--) {
        cin >> n >> m >> k;
        l = k - 1;
        r = k - 1;
        ans = 1;
        while (r < n) {
            l = l * m + 1;
            r = r * m + m;
            if (l >= n) {
                break;
            }
            ans += min(r, n - 1) - l + 1;
        }
        cout << ans << endl;
    }

    return 0;
}

你可能感兴趣的:(蓝桥杯,算法,c++)