如果直接用暴力解法,逐个判断其他的数是不是它的约数,这样时间复杂度是O(n2)O(n^2),超时。

假设A1A_1A2A_2的约数的话,那么A2A_2就是A1A_1的倍数.因此可以做这么一个处理,当判定某个数字AkA_k时,我们可以把这个数字的倍数AmA_m全部加11,含义时,AmA_m的约数又多了一个。

考虑到可能会有很多AkA_k的值相同,所以可以利用桶的思想,把相同的一次性统计完。

for(int i = 0; i < n; i++)
{
    cin >> a[i];
    cnt[a[i]] ++;
}

cnt[i]!=0cnt[i] != 0,即有某个AkA_k出现了,将所有AkA_k的倍数都加上cnt[Ak]cnt[A_k]

for(int i = 1; i < N; i++)
{
	if(cnt[i] == 0) continue;
	for(int j = i; j < N; j += i) {
		res[j] += cnt[i];
	} 
}

n + n/2 + n/3 + ... n / n = nlogennlog_en

时间复杂度是O(nlogen)O(nlog_en)

总结:约数和倍数是一对好基友,当求约数的时间复杂度过大时,可以考虑倍数