专栏文章

题解:B4398 [蓝桥杯青少年组国赛 2025] 第三题

B4398题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mio26770
此快照首次捕获于
2025/12/02 12:08
3 个月前
此快照最后确认于
2025/12/02 12:08
3 个月前
查看原文
说点题外话:当时蓝桥杯我只过了第一题
看到这题,首先就想到了dp解法,这道题和有一道 dp 非常像,但这个要求是乘法。
我们先来看完全平方数的定义:
完全平方数:一个整数,它可以表示为另一个整数的平方。例如,3636 是一个完全平方数,因为 36=6×636 = 6 \times 6
题目要求每两个数两两相乘的积为完全平方数,也就是说,因子必须成双成对的出现。
那既然牵扯到了因子,为什么不考虑分解质因数呢?
分解质因数可以很好的处理因子数量和因子的问题。
普通的分解质因数肯定是不行了,数据范围一看就知道了。那就只有一个办法:先用线性筛筛出来质数,再分解质因数。线性筛不会可移步至
线性筛代码CPP
//d[i]表示为 i 的质因子
void init(){
    for (int i = 2; i <= M; i++){
        if (!d[i]) p.push_back(i), d[i] = i; //如果是质数,放入p数组中
        for (int j = 0; p[j] <= M / i; j++){
            d[p[j] * i] = p[j];
            if (i % p[j] == 0) break;
        }
    }
}
线性筛的代码可能比普通的不一样,请好好理解。
我们筛出来了 ii 的因子,分解质因数也就好写了。
因为要求为两两相乘的完全平方数,我们就可以忽略掉完全平方数因子。
证明一下:
因为要求乘积为完全平方数,举两个数的例子:
18=2×3×318 = 2 \times 3 \times 3
8=2×2×28 = 2 \times 2 \times 2
18×8=2×2×2×2×3×3=24×32\begin{aligned} 18 \times 8 &= 2 \times 2 \times 2 \times 2 \times 3 \times 3 \\ &= 2^4 \times 3^2 \end{aligned}
为完全平方数。
若忽略掉因子,则:
1818 最终转化为 22
88 最终转化为 22
相乘得 4=224 = 2^2,与不去掉因子结果一致,也是完全平方数。
也就是说,可以忽略完全平方数因子。
那我们就可以在分解质因数过程中处理。
具体看代码吧。
AC代码CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int M = 1e7 + 5;
int a[N], d[M], c[M];
vector<int> p;
void init(){
    for (int i = 2; i <= M; i++){
        if (!d[i]) p.push_back(i), d[i] = i;
        for (int j = 0; p[j] <= M / i; j++){
            d[p[j] * i] = p[j];
            if (i % p[j] == 0) break;
        }
    }
}
int main(){
    int n, res = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    init();
    vector<int> v(M);
    for (int i = 1; i <= n; i++){
        int ans = 1;
        while (a[i] > 1){
            if (ans % d[a[i]] == 0) ans /= d[a[i]];
            else ans *= d[a[i]];
            a[i] /= d[a[i]];
        }
        v[ans]++;
        res = max(res, v[ans]);
    }
    printf("%d", res);
    return 0;
}
如有错误地方敬请读者指出。

评论

0 条评论,欢迎与作者交流。

正在加载评论...