Python 3 AC Solution with detailed math derivation
\nclass Solution:\n    def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:\n        """\n        Binary Search\n        find first 
```\nclass Solution:\n    def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:\n        """\n        Binary Search\n        find first number that makes countSmallerOrEqual(number) >= k\n        return number\n        """\n        boundary = [nums1[0]*nums2[0], nums1[0] * nums2[-1], nums1[-1] * nums2[0], nums1[-1] * nums2[-1]]\n        low, high = min(boundary), max(boundary)\n        while low + 1 < high:\n            mid = low + (high - low) // 2\n            if self.countSmallerOrEqual(mid, nums1, nums2) >= k:\n                high = mid\n            else:\n                low = mid + 1\n        if self.countSmallerOrEqual(low, nums1, nums2) >= k:\n            return low\n        else:\n            return high\n    \n    def countSmallerOrEqual(self, m, nums1, nums2):\n        """\n        Two pointers solution\n        use monotonic property of both nums1 and nums2\n        return the number of products nums1[i] * nums2[j] <= m\n        l1, l2 = len(nums1), len(nums2)\n           \n        1) if m >= 0, \n        ***Given nums1[i] < 0***\n        find j such that nums2[j] >= m/nums1[i]\n        i increases - > nums1[i] increases -> m/nums1[i] decreases -> index j decreases\n        j monotonically moves left\n        return j:l2 -> l2 - j + 1\n        *** Given nums1[i] = 0\n        return l2\n        ***Given nums1[i] > 0***\n        find j such that nums2[j] <= m/nums1[i]\n        i increases - > nums1[i] increases -> m/nums1[i] decreases -> index j decreases\n        j monotonically moves left\n        return 0:j -> j + 1\n\n        2) if m < 0, \n        ***Given nums1[i] < 0***\n        find j such that nums2[j] >= m/nums1[i]\n        i increases - > nums1[i] increases -> m/nums1[i] increases -> index j increases\n        j monotonically moves right\n        return j:l2 -> l2 - j + 1\n        *** Given nums1[i] = 0\n        return 0\n        ***Given nums1[i] > 0***\n        find j such that nums2[j] <= m/nums1[i]\n        i increases - > nums1[i] increases -> m/nums1[i] increases -> index j increases\n        j monotonically moves right\n        return 0:j -> j + 1\n        \n        """\n        l1, l2 = len(nums1), len(nums2)\n        ans = 0\n        if m >= 0:\n            j1, j2 = l2-1, l2-1\n            for i in range(l1):\n                if nums1[i] < 0:\n                    while j1 >=0 and nums2[j1] >= m/nums1[i]:\n                        j1 -= 1\n                    ans += l2 - j1 - 1\n                elif nums1[i] > 0:\n                    while j2 >=0 and nums2[j2] > m/nums1[i]:\n                        j2 -= 1\n                    ans += j2 + 1\n                else:\n                    ans += l2\n        else:\n            j1, j2 = 0, 0\n            for i in range(l1):\n                if nums1[i] < 0:\n                    while j1 < l2 and nums2[j1] < m/nums1[i]:\n                        j1 += 1\n                    ans += l2 - j1\n                elif nums1[i] > 0:\n                    while j2 < l2 and nums2[j2] <= m/nums1[i]:\n                        j2 += 1\n                    ans += j2\n        return ans\n```\n                    \n
['Two Pointers', 'Binary Tree', 'Python3']