给你一个下标从 0 开始、长度为 n 的整数数组 nums 和一个整数 k ,返回满足下述条件的下标对 (i, j) 的数目:
0 <= i < j <= n - 1 且
nums[i] * nums[j] 能被 k 整除。
示例 1:
输入:nums = [1,2,3,4,5], k = 2
输出:7
解释:
共有 7 对下标的对应积可以被 2 整除:
(0, 1)、(0, 3)、(1, 2)、(1, 3)、(1, 4)、(2, 3) 和 (3, 4)
它们的积分别是 2、4、6、8、10、12 和 20 。
其他下标对,例如 (0, 2) 和 (2, 4) 的乘积分别是 3 和 15 ,都无法被 2 整除。
示例 2:
输入:nums = [1,2,3,4], k = 5
输出:0
解释:不存在对应积可以被 5 整除的下标对。
提示:
1 <= nums.length <= 10^5
1 <= nums[i], k <= 10^5
解题思路
最大公倍数+统计,最要是计算K/GCD(Ni,K) 在数组中出现的次数。
-spec count_pairs(Nums :: [integer()], K :: integer()) -> integer().
count_pairs(Nums, K) ->
Map = maps:new(),
Map1 = init_map(Nums, Map),
Max = lists:max(Nums),
Map2 = count_map(1, Max, Map1),
do_count(Nums, K, Map2, 0).
do_count([], K, Map, Ans) ->
Ans div 2;
do_count([N | Nums], K, Map, Ans) ->
M = K div gcd(N, K),
Ans1 = Ans + maps:get(M, Map, 0),
if
(N * N) rem K =:= 0 ->
do_count(Nums, K, Map, Ans1 -1);
true ->
do_count(Nums, K, Map, Ans1)
end.
init_map([], Map) ->
Map;
init_map([N | Nums], Map) ->
Map1 = add_to_map(N, Map, 1),
init_map(Nums, Map1).
count_map(I, Max, Map) when I > Max->
Map;
count_map(I, Max, Map) ->
NewMap = count_map1(I*2, Max, I, Map),
count_map(I + 1, Max, NewMap).
count_map1(J, Max, I, Map) when J > Max ->
Map;
count_map1(J, Max, I, Map) ->
Value = maps:get(J, Map, 0),
if
Value =/= 0 ->
NewMap = add_to_map(I, Map, Value),
count_map1(J + I, Max, I, NewMap);
true ->
count_map1(J + I, Max, I, Map)
end.
add_to_map(Key, Map, Num) ->
case maps:find(Key, Map) of
{ok, Value} ->
maps:update(Key, Value + Num, Map);
_ ->
maps:put(Key, Num, Map)
end.
gcd(0, Max) ->
Max;
gcd(Min, Max) ->
if
Min > Max ->
gcd(Min rem Max, Max);
true ->
gcd(Max rem Min, Min)
end.