ABC393E题解

大概评级:绿。

拿到题目,寻找突破口,发现 \(A_i \le 10^6\),一般的数据都是 \(A_i \le 10^9\),所以必有蹊跷。

数学,权值,最大公约数,联想到了因子……懂了,原来是这么做!

首先一个数 \(x\) 如果能做最大公约数,那么 \(A_i\) 一定是 \(x\) 的倍数,并且总共有至少 \(K\) 个数是 \(x\) 的倍数(包含 \(A_i\)),那么我们肯定是需要一个数组来处理对于一个数在 \(A\) 中有多少个数是它的倍数,但根据我们的直觉,在这个数组之前应该还需要设置一个数组处理对于一个数它在 \(A\) 中出现了多少次,我们设处理对于一个数它在 \(A\) 中出现了多少次的数组为 \(num\),处理对于一个数在 \(A\) 中有多少个数是它的倍数的数组为 \(s\),那么显然 \(f_d = \sum_{d|n} s_n\),于是直接使用类似埃氏筛法的东西求出 \(f\) 数组,如果设 \(M = \max_{i = 1}^n A_i\),那么求出 \(f\) 数组的时间复杂度为 \(O(M \log M)\),求出 \(s\) 数组就不用说了,\(O(N)\) 地一边读入一边统计就行了,最后有了 \(f\) 数组的辅助,是很好求出答案的,我们设 \(A_i\) 的答案为 \(ans_i\)\(ans_i = \max_{d|n,t_d \ge K}d\),很好理解吧,于是我们发现这玩意也可以使用一种类似埃氏筛的方法求,于是这道题就结束了。

总时间复杂度:\(O(N+M \log M+M \log M+N) = O(N+M \log M)\)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1.2e6+5;
int num[N],t[N],ans[N],a[N];
int main()
{
	int n,k;
	scanf("%d %d",&n,&k);
	int maxx = 0;
	for(int i = 1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		maxx = max(maxx,a[i]);
		num[a[i]]++;
	}
	for(int i = 1;i<=maxx;i++)
	{
		for(int j = i;j<=maxx;j+=i)
		{
			t[i]+=num[j];	
		}
	}
	for(int i = 1;i<=maxx;i++)
	{
		if(t[i]<k)
		{
			continue;
		}
		for(int j = i;j<=maxx;j+=i)
		{
			ans[j] = max(ans[j],i);
		}
	}
	for(int i = 1;i<=n;i++)
	{
		printf("%d\n",ans[a[i]]);
	}
    return 0;
}
posted @ 2025-02-17 22:04  林晋堃  阅读(15)  评论(0)    收藏  举报