算法分析
问题:对于每个Ai
,在其他数中由多少个数是它的约数?
可以通过反向求解,对于某个因子P
,P
的k
倍是Ai
,则表示P
是Ai
的约数
cnt[i]
数组表示该数i
有多少个,ans[j]
数组表示该数j
有多少个其他数作为它的约数,若i * k == j
,则i
可以作为j
的约数,因此ans[j] += cnt[i]
for(int i = 1;i < M;i ++)
{
for(int j = i;j < M;j += i)
ans[j] += cnt[i];
}
虽然是两重循环,可是对于每个i
,只运行$\frac{M}{i}$次,则所有的i
的运行次数的总和是$\frac{M}{1} + \frac{M}{2} + … + \frac{M}{N} = MlogM$
时间复杂度$O(nlogn)$
参考文献
算法提高课
Java 代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
static int N = 100010,M = 1000010;
static int[] a = new int[N];
static int[] cnt = new int[M];
static int[] ans = new int[M];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
for(int i = 0;i < n;i ++)
{
a[i] = Integer.parseInt(br.readLine());
cnt[a[i]] ++;
}
for(int i = 1;i < M;i ++)
{
for(int j = i;j < M;j += i)
ans[j] += cnt[i];
}
for(int i = 0;i < n;i ++)
{
log.write(ans[a[i]] - 1 + "\n");
}
log.flush();
}
}