← Home
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

type FastScanner struct {
	r *bufio.Reader
}

func (fs *FastScanner) NextInt64() int64 {
	var sign int64 = 1
	var val int64
	c, _ := fs.r.ReadByte()
	for (c < '0' || c > '9') && c != '-' {
		c, _ = fs.r.ReadByte()
	}
	if c == '-' {
		sign = -1
		c, _ = fs.r.ReadByte()
	}
	for c >= '0' && c <= '9' {
		val = val*10 + int64(c-'0')
		c2, err := fs.r.ReadByte()
		if err != nil {
			break
		}
		c = c2
		if c < '0' || c > '9' {
			break
		}
	}
	return val * sign
}

type Task struct {
	a int64
	b int
}

type Group struct {
	a    int64
	cnt  int
	pref []int64
}

func main() {
	in := &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	defer out.Flush()

	n := int(in.NextInt64())
	a := make([]int64, n)
	b := make([]int, n)

	for i := 0; i < n; i++ {
		a[i] = in.NextInt64()
	}
	for i := 0; i < n; i++ {
		b[i] = int(in.NextInt64())
	}

	tasks := make([]Task, n)
	var hi int64
	for i := 0; i < n; i++ {
		tasks[i] = Task{a: a[i], b: b[i]}
		if 1000*a[i] > hi {
			hi = 1000 * a[i]
		}
	}

	sort.Slice(tasks, func(i, j int) bool {
		if tasks[i].a == tasks[j].a {
			return tasks[i].b > tasks[j].b
		}
		return tasks[i].a > tasks[j].a
	})

	var groups []Group
	for i := 0; i < n; {
		j := i
		var bs []int
		for j < n && tasks[j].a == tasks[i].a {
			bs = append(bs, tasks[j].b)
			j++
		}
		sort.Slice(bs, func(x, y int) bool { return bs[x] > bs[y] })
		pref := make([]int64, len(bs)+1)
		for k := 0; k < len(bs); k++ {
			pref[k+1] = pref[k] + int64(bs[k])
		}
		groups = append(groups, Group{
			a:    tasks[i].a,
			cnt:  len(bs),
			pref: pref,
		})
		i = j
	}

	feasible := func(m int64) bool {
		const negInf int64 = -1 << 60
		dp := make([]int64, n+1)
		for i := range dp {
			dp[i] = negInf
		}
		dp[0] = 0

		for _, g := range groups {
			ndp := make([]int64, n+1)
			for i := range ndp {
				ndp[i] = negInf
			}
			for c := 0; c <= n; c++ {
				if dp[c] == negInf {
					continue
				}
				minR := g.cnt - c
				if minR < 0 {
					minR = 0
				}
				for r := minR; r <= g.cnt; r++ {
					c2 := c - g.cnt + 2*r
					val := dp[c] + m*g.pref[r] - 1000*g.a*int64(r)
					if val > ndp[c2] {
						ndp[c2] = val
					}
				}
			}
			dp = ndp
		}

		for c := 0; c <= n; c++ {
			if dp[c] >= 0 {
				return true
			}
		}
		return false
	}

	var lo int64
	for lo < hi {
		mid := (lo + hi) / 2
		if feasible(mid) {
			hi = mid
		} else {
			lo = mid + 1
		}
	}

	fmt.Fprintln(out, lo)
}