Alternate way to compute product of pairwise sums mod 10^9+7 faster than O(N^2)

后端 未结 2 1265
臣服心动
臣服心动 2021-02-02 14:30

Given an array A of integers of size N, I want to compute

2条回答
  •  情歌与酒
    2021-02-02 15:09

    Since ai <= 200.000 and N<=200.000, there might be 40.000.000.000 terms in total, but you know that ai + aj <= 400.000. There can be at most 400.000 unique terms. That's already 5 orders of magnitude better.

    However, most of these terms aren't primes; there only ~40.000 primes under 400.000. You may end up with a somewhat higher multiplicity of each individual term, but that's not a big deal. Calculating (prime^N) modulo 1000000007 is fast enough even for big X.

    You can reasonably pre-calculate the factorization of all numbers <=400.000 and get the primes <=400.000 as a free side-effect.

    This method achieves a speed-up because we delay multiplication, and instead count small prime factors found through a lookup. By the time we need to do the multiplications, we have a series of exponents and can use repeated squaring to efficiently reduce them.

    It's counter-intuitive perhaps that we use prime factorization as a speed-up, when the "well-known fact" is that prime factorization is hard. But this is possible because each term is small, and we repeatedly need the same factorization.

    [edit] From the comments, it seems that figuring out the multiplicity of ai+aj is hard, since you can only count the terms where i. But that's a non-issue. Count the multiplicity of all terms ai+aj, and divide by two since aj+i==ai+aj. This is only wrong for the diagonal where i==j. This is fixed by adding the multiplicity of all terms ai+ai prior to dividing by 2.

    Ex: a={1 2 3}, terms to consider are {1+1, 1+2, 1+3, 2+2, 2+3, 3+3} [triangle]. The multiplicity of 4 is 2 (via 1+3 and 2+2). Instead, consider {1+1, 1+2, 1+3, 2+1, 2+2, 2+3, 3+1, 3+2, 3+3} [square] + {1+1, 2+2, 3+3} [diagonal]. The multiplicity of 4 is now 4 (1+3,2+2,3+1 and 2+2), divide by 2 to get the correct result.

    And since the order of a[] no longer matters for the square variant, you can use a counting sort on it. E.g. given {4,5,6,5}, we get 4:1, 5:2, 6:1. Thus the multiplicity of 10 is 4+6:1, 5+5:2, 6+4:1

提交回复
热议问题