✏️ 纠错
第 135 题 / 共 155 题

题目描述

给定一棵有 109 个结点的有根树,这些结点依次以 1,2,…,109 编号,根结点的编号为 1。对于编号为 k(2≤k≤109)的结点,其父结点的编号为 k 的因数中除 k 以外最大的因数。

现在有 q 组询问,第 i(1≤i≤q)组询问给定 xi​,yi​,请你求出编号分别为 xi​,yi​ 的两个结点在这棵树上的距离。两个结点之间的距离是连接这两个结点的简单路径所包含的边数。

输入格式

第一行,一个正整数 q,表示询问组数。

接下来 q 行,每行两个正整数 xi​,yi​,表示询问结点的编号。

输出格式

输出共 q 行,每行一个整数,表示结点 xi​,yi​ 之间的距离。

输入输出样例

输入 #1

3
1 3
2 5
4 8

输出 #1

1
2
1

输入 #2

1
120 650

输出 #2

9

说明/提示

对于 60% 的测试点,保证 1≤xi​,yi​≤1000。

对于所有测试点,保证 1≤q≤1000,1≤xi​,yi​≤109。

📝 题目解析

【题目大意】在一棵树上,每个节点的祖先被定义为该节点自身以外的最大因数,现需求解树上任意两点之间的距离。 根据数据范围要求,最大因数不包含此数,最小因数不包含1。

【考纲知识点】数学知识

【解题思路】从小到大找到所有的因数,然后从x起,x除以最小的因数得到了x的父亲节点x’“除x本身外最大的因数”,然后x’再除以第二小的因数得到x’的父亲节点。在此期间,统计因数的个数,相加即可得到结果。注意是多组测试数据。

参考程序
 

#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 50;

int q;
int a[N], cnta;
int b[N], cntb;
int f[N], t;

void factorize(int x, int a[], int &cnt) {
    a[0] = x;
    t = 0;
    for (int i = 2; i * i <= x; i++)
        while (x % i == 0) {
            f[++t] = i;
            x /= i;
        }
    if (x > 1)
        f[++t] = x;
    for (int i = 1; i <= t; i++)
        a[i] = a[i - 1] / f[i];
    cnt = t;
}

int main() {
    scanf("%d", &q);
    while (q--) {
        int x, y;
        scanf("%d%d", &x, &y);
        factorize(x, a, cnta);
        factorize(y, b, cntb);
        int px = 0, py = 0;
        while (a[px] != b[py]) {
            if (a[px] > b[py])
                px++;
            else
                py++;
        }
        printf("%d\n", px + py);
    }
    return 0;
}