The Sum of Legal Set

https://blog.csdn.net/qq_46105170/article/details/110621205

给定一个长n nn的数组A AA和一个整数k kk,问A AA有多少个子集使得其最大最小值之和是小于等于k kk的。答案模1 0 9 + 7 10^9+710 9 +7后返回。空子集不算。

先对A AA排序,接着用对撞双指针,枚举最小最大值。设指针i ≤ j i\le ji≤j,如果A [ i ] + A [ j ] ≤ k A[i]+A[j]\le kA[i]+A[j]≤k,说明以A [ i ] A[i]A[i]为最小值,A [ i : j ] A[i:j]A[i:j]为最大值的子集都是满足条件的,这样的子集的个数就是2 j − i 2^{j-i}2 j−i 个,计算完这样的子集之后,将i ii右移;否则如果A [ i ] + A [ j ] > k A[i]+A[j]> kA[i]+A[j]>k,则左移j jj。至于求2 k 2^k2 k ,可以用快速幂来做,时间复杂度可以降到O ( log ⁡ k ) O(\log k)O(logk),具体参考https://blog.csdn.net/qq_46105170/article/details/104338070。代码如下: ————————————————

原文链接:https://blog.csdn.net/qq_46105170/article/details/110621205

import java.util.Arrays;

public class Solution {
    /**
     * @param a: the array
     * @param k: the target
     * @return: the sum of the legal set
     */
    public int theSumofLegalSet(int[] a, int k) {
        // Write your code here.
        Arrays.sort(a);
        
        long res = 0, MOD = (long) (1E9 + 7);
        for (int i = 0, j = a.length - 1; i <= j; ) {
            if (a[i] + a[j] <= k) {
                res += pow2(j - i, MOD);
                res %= MOD;
                i++;
            } else {
                j--;
            }
        }
        
        return (int) res;
    }
    
    private long pow2(int n, long MOD) {
        long res = 1, p = 2;
        while (n > 0) {
            if ((n & 1) == 1) {
                res *= p;
                res %= MOD;
            }
            
            p *= p;
            p %= MOD;
            
            n >>= 1;
        }
        
        return res;
    }
}

pow(x,n)

算x n x^nx n 。

思路是快速幂(exponentiating by squaring)。主要思路是对n nn做二进制展开,然后对这些二进制位从右向左扫描,用一个变量来保存到当前这个二进制位,x xx的那么多次次方的结果是多少。

设r rr是答案。举个例子来说,如果要算x 13 x^{13}x 13 ,由于13 = ( 1101 ) 2 13=(1101)_213=(1101) 2 ​ ,x xx首先保存的是x 2 0 x^{2^0}x 2 0

是多少,也就是x 1 x^1x 1 ,那其实就是x xx。接着开始从右向左扫描1101 11011101,扫描到第0 00位时遇到1 11,就给r rr乘上x 2 0 x^{2^0}x 2 0

,同时x xx需要平方一下,这样就保存了x 2 1 x^{2^1}x 2 1

这个值,扫描到第1 11位时遇到0 00,r rr保持原样,而x xx继续平方一下,得到了x 2 2 x^{2^2}x 2 2

,继续扫描到1 11,这时r rr乘一下x 2 2 x^{2^2}x 2 2

,如此下去r rr又乘了x 2 3 x^{2^3}x 2 3

,扫描结束。我们统计一下会发现,r = x 2 0 × x 2 2 × x 2 3 = x 2 0 + 2 2 + 2 3 = x 13 r=x^{2^0}\times x^{2^2}\times x^{2^3}=x^{2^0+2^2+2^3}=x^{13}r=x 2 0

×x 2 2

×x 2 3

=x 2 0 +2 2 +2 3

=x 13 ,正好是所求结果。代码如下: ————————————————

原文链接:https://blog.csdn.net/qq_46105170/article/details/104338070


class Solution {
 public:
  double myPow(double x, int m) {
    double res = 1.0;
    long long n = m;
    if (n < 0) x = 1.0 / x;
    n = abs(n);
    while (n) {
      if (n & 1) res *= x;
      x *= x;
      n >>= 1;
    }
    return res;
  }
};

Last updated

Was this helpful?