【洛谷】题解 P1414 又是毕业季II -数论

题意

求从n个数中取i个数的最大的最大公约数 (i从1到k)

输入

二行

第一行两个整数n和k

第二行k个数ai (i∈[1,k])

输出

n行 分别表示取i个数的最大公约数

【数据范围】

记输入数据中能力值的最大值为inf。

对于20%的数据,n<=5,inf<=1000

对于另30%的数据,n<=100,inf<=10

对于100%的数据,n<=10000,inf<=1e6

题解

一开始简单的想到了一个递推式: 取i个数的最大公约数是取i-1个数的最大公约数和其他未用过的数的最大的最大公约数

即f[i] = max (f[i], gcd (f[i-1], a[j])) (i∈[1, n], j∈[1,k])

但可想而知,这个算法的时间复杂度太大了

那么我们考虑到对ai分别求出其因数并计数,即记录a1到an的数的因数分别出现了几次,得到计数数组c[N] N = max (a1 ~ an);

在考虑之前的递推式,很显然取1个数的时候答案为最大的因数,取i个数时的答案很显然要小于等于取i-1个数的答案

所以我们从a1到an中的最大值开始向下搜索:

如果该数num的c[num] >= i 便满足要求输出即可

AC代码

#include <bits/stdc++.h>
using namespace std;

static const int N = 1e6 + 10;
int n, _max = 0, c[N];

int main ()
{
	scanf ("%d", &n);
	for (int i = 1; i <= n; ++i)
	{
		int num;
		scanf ("%d", &num);
		_max = max (_max, num);
		int m = sqrt (num);
		for (int i = 1; i <= m; ++i)
			if (num % i == 0)
			{
				++c[i];
				if (num != i * i)
					++c[num/i];
			}
	}
	int num = _max;
	for (int i = 1; i <= n; ++i)
	{
		for (; c[num] < i ;)
			--num;
		printf ("%d\n", num);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值