题目:
洛谷2926
(截止至本博客发表时,BZOJ1607题面有误,正确题面请到洛谷2926查看)
分析:
一句话题意:给定
n
n
个数,求对于每个
ai
a
i
有多少个数
aj
a
j
满足
ai|aj
a
i
|
a
j
(1≤i,j≤n
(
1
≤
i
,
j
≤
n
且
i≠j)
i
≠
j
)
按题意模拟的话
O(n2)
O
(
n
2
)
肯定过不去。考虑对于一个数
ai
a
i
,它仅会对所有
ai∗k(1≤k
a
i
∗
k
(
1
≤
k
且
k
k
为整数) 产生1的贡献。于是可以用的时间给所有
ans[ai∗k]
a
n
s
[
a
i
∗
k
]
加上1 (
ans[x]
a
n
s
[
x
]
表示有多少个
ai
a
i
能整除
x
x
) ,据说这样的复杂度是的
注意可能有多个
ai
a
i
相等,枚举
ai
a
i
可能会多次执行相同的操作,费时间。用
cnt[x]
c
n
t
[
x
]
记录有多少个
i
i
满足。枚举
x
x
,每个对
kx
k
x
的贡献是
cnt[x]
c
n
t
[
x
]
以及一头牛不会拍自己的头,所以最终答案是
ans[ai]−1
a
n
s
[
a
i
]
−
1
(详见代码)
代码:
#include <cstdio>
using namespace std;
namespace zyt
{
const int M = 1e6 + 10, N = 1e5 + 10;
void work()
{
static int ans[M], cnt[M], arr[N];
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &arr[i]);
cnt[arr[i]]++;
}
for (int i = 1; i <= M; i++)
if (cnt[i])
for (int j = i; j <= M; j += i)
ans[j] += cnt[i];
for (int i = 1; i <= n; i++)
printf("%d\n", ans[arr[i]] - 1);
}
}
int main()
{
zyt::work();
return 0;
}