又一道 GCD 问题
题目链接:nowcoder 213804
到主站看:https://blog.csdn.net/weixin_43346722/article/details/112740731
题目大意
给你一个数组,要你求出从他们中选出  个的 gcd 的最大值。
思路
看到这道题,我们考虑看有多少个数有  这个因子,设其为 
。
那我们分解一下质因子(用素数筛选法和 floor(sqrt()) 来加速),然后 dfs 一下,就可以得到一个数的每个因子,就从而求出了 。
那有了这个,我们可以求出要选出  个数的 gcd 最大值是多少了。
(就是从后往前搜第一个  大于等于 
 的数)
那我们可以先弄出刚刚好是  个数的,然后再从后往前跑最大值。
然后就可以得出答案了。
具体实现可以看看代码。
代码
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
int n, a[100001], su[50001], all[100001], tmpn, tmp, ans[100001], maxn, zyz[1001], numm[1001];
bool susu[100100];
void getsusu() {//素数筛选法筛出素数
    susu[1] = susu[0] = 1;
    for (int i = 2; i <= maxn + 100; i++)
        if (!susu[i]) {
            su[++su[0]] = i;
            for (int j = i + i; j <= maxn + 100; j += i)
                susu[j] = 1;
        }
}
void dfs(int now, int sum) {
    if (now == zyz[0] + 1) {
        all[sum]++;
        return ;
    }
    int tmpp = 1;
    for (int i = 0; i <= numm[now]; i++) {//对于这一个因数,选多少个乘
        dfs(now + 1, sum * tmpp);
        tmpp *= zyz[now];
    }
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        maxn = max(maxn, a[i]);
        ans[i] = 1;
    }
    getsusu();
    for (int i = 1; i <= n; i++){
        zyz[0] = 0;//分解质因数
        tmpn = a[i];
        tmp = floor(sqrt(a[i]));
        for (int j = 1; su[j] <= tmpn && j <= tmp; j++) {
            if (tmpn % su[j] == 0) {
                zyz[++zyz[0]] = su[j];
                numm[zyz[0]] = 0;
                while (tmpn % su[j] == 0) {
                    numm[zyz[0]]++;
                    tmpn /= su[j];
                }
            }
        }
        if (tmpn != 1) {
            zyz[++zyz[0]] = tmpn;
            numm[zyz[0]] = 1;
        }
        dfs(1, 1);//标记每一个因数
    }
    for (int i = maxn; i >= 1; i--) {
        if (ans[all[i]] == 1) ans[all[i]] = i;
    }
    for (int i = n - 1; i >= 2; i--)//选 i 个也可以在 i+x 个中选 i 个,不一定要刚刚好
        ans[i] = max(ans[i + 1], ans[i]);
    for (int i = 2; i <= n; i++) printf("%d ", ans[i]);
    return 0;
} 
京公网安备 11010502036488号