CodeEff/ECCO huggingface dataset:
# Original solution
from collections import Counter

n = int(eval(input()))
d = list(map(int, input().split()))
mod = 998244353

a = sorted(list(set(d)))

if d[0] != 0:
    ans = 0
elif a[-1] != len(a)-1:
    ans = 0
else:
    c = sorted(Counter(d).items())
    if c[0] != (0, 1):
        ans = 0
    else:
        ans = 1
        pre = 1
        for k, v in c:
            ans *= pre ** v
            ans %= mod
            pre = v

print(ans)

# Optimized solution
n = int(eval(input()))
d = list(map(int, input().split()))
mod = 998244353

a = [0] * n
for d_ in d:
    a[d_] += 1

res = d[0] == 0 and a[0] == 1
pre = 1
for a_ in a:
    res *= pre ** a_
    res %= mod
    pre = a_

print(res)
# Original solution
n = int(eval(input()))
d = list(map(int, input().split()))
mod = 998244353

a = [0] * n
for d_ in d:
    a[d_] += 1

res = d[0] == 0 and a[0] == 1
pre = 1
for a_ in a:
    res *= pre ** a_
    res %= mod
    pre = a_

print(res)

# Optimized solution
n = int(eval(input()))
d = list(map(int, input().split()))
mod = 998244353

a = [0] * n
for d_ in d:
    a[d_] += 1

res = d[0] == 0 and a[0] == 1
pre = 1
for a_ in a:
    res = res * pre ** a_ % mod
    pre = a_

print(res)
# Original solution
n=int(eval(input()))
d=list(map(int,input().split()))
maxd=max(d)
import collections
counter=collections.Counter(d)
if d[0]!=0 or counter[0]!=1:
  print((0))
else:
  a=1
  ans=1
  for i in range(1,maxd+1):
    if i not in counter:
      print((0))
      break
    else:
      b=counter[i]
      ans*=(a**b)
      a=b
  else:
    print((ans%998244353))


# Optimized solution
n=int(eval(input()))
d=list(map(int,input().split()))

if d[0]!=0:
  print((0))
  exit(0)
  
m=max(d)
counts=[0]*(m+1)

import collections
counter=collections.Counter(d)

for key,val in list(counter.items()):
  counts[key]=val
if counts[0]!=1:
  print((0))
  exit(0)
ans=1
div=998244353
for i in range(1,len(counts)):
  ans*=pow(counts[i-1],counts[i],div)
  ans%=div
  
print(ans)
# Original solution
n = int(eval(input()))
ls = list(map(int, input().split(' ')))
ans = 1
if ls[0] != 0:
    ans = 0
m = max(set(ls))
d = {i: ls.count(i) for i in range(m+1)}
for i in range(1, m+1):
    ans = (ans * (d[i-1] ** d[i]) % 998244353) % 998244353
print(ans)


# Optimized solution
n = int(eval(input()))
ls = list(map(int, input().split(' ')))
m = max(set(ls))
d = {}
for l in ls:
    d[l] = d.get(l, 0) + 1
ans = 0 if (ls[0] != 0 or d.get(0) >= 2) else 1
for i in range(1, m+1):
    if i not in d:
        ans = 0
    ans = (ans * (d.get(i-1, 0) ** d.get(i, 0))) % 998244353 
print(ans)
# Original solution
n,*a=list(map(int,open(0).read().split()))
mod=998244353
d={}
for i in a:
  d[i]=d.get(i,0)+1
b=list(d.items())
b.sort()
ans=1
if a[0]!=0 or len(b)!=b[-1][0]+1 or b[0][1]!=1:
    ans=0
for i in range(1,len(b)):
    ans*=b[i-1][1]**b[i][1]
    ans%=mod
print(ans)

# Optimized solution
n,*a=list(map(int,open(0).read().split()))
mod=998244353
b=[0]*n
for i in a:
    b[i]+=1
ans=0
if a[0]==0 and 1==b[0]:
    ans=1
for i,j in zip(b,b[1:]):
    ans=ans*i**j%mod
print(ans)
# Original solution
N=int(eval(input()))
D=list(map(int,input().split()))

mod=998244353

if D[0]!=0:
    print((0))
    exit()

n=[0]*N
n[0]=1
for i in range(1,N):
    if D[i]==0:
        print((0))
        exit()
    n[D[i]]+=1

ans=1
cnt=n[0]+n[1]
for i in range(2,N):
    if n[i]==0:
        if cnt!=N:
            print((0))
            exit()
        else:
            break
    ans=ans*n[i-1]**n[i]
    ans=ans%mod
    cnt=cnt+n[i]
print(ans)


# Optimized solution
N=int(eval(input()))
D=list(map(int,input().split()))
mod=998244353

if D[0]!=0:
    print((0))
    exit()


B=[0]*N
for d in D:
    B[d]+=1
if B[0]!=1:
    print((0))
    exit()

ans=1
total=1
for i in range(1,N):
    if B[i]==0:
        if total!=N:
            print((0))
            exit()
        else:break
    total+=B[i]
    ans*=(B[i-1]**B[i])
    ans%=mod

print(ans)
# Original solution
while 1:
    n,w,d = list(map(int,input().split()))
    if w == 0: break
    cake = [[w,d]]
    for loop in range(n):
        p,s = list(map(int,input().split()))
        x,y = cake.pop(p-1)
        s %= (x+y)
        if s < x:
            x1,x2 = sorted([s,x-s])
            cake.append([x1,y])
            cake.append([x2,y])
        else:
            s -= x
            y1,y2 = sorted([s,y-s])
            cake.append([x,y1])
            cake.append([x,y2])
    print(" ".join(map(str,sorted([x*y for x,y in cake]))))

# Optimized solution
while 1:
    n,w,d = list(map(int,input().split()))
    if w == 0: break
    cake = [[w,d]]
    for loop in range(n):
        p,s = list(map(int,input().split()))
        x,y = cake.pop(p-1)
        s %= (x+y)
        if s < x:
            x1,x2 = sorted([s,x-s])
            cake += [[x1,y],[x2,y]]
        else:
            s -= x
            y1,y2 = sorted([s,y-s])
            cake += [[x,y1],[x,y2]]
    print(" ".join(map(str,sorted([x*y for x,y in cake]))))
# Original solution
#!/usr/bin/env python3
import sys
import collections

def solve(N: int, A: "List[int]"):
    counter = sorted(list(collections.Counter(A).values()),reverse=True)
    for i in range(1,N+1):
        if len(counter)<i:
            print((0))
            continue
        c_index = 0
        n = N
        k = i 
        while counter[c_index]*k > n and c_index<len(counter)-1:
            n-=counter[c_index]
            c_index+=1
            k-=1
        print((n//k))
    return

def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    solve(N, A)

if __name__ == '__main__':
    main()


# Optimized solution
#!/usr/bin/env python3
import sys
import collections

def solve(N: int, A: "List[int]"):
    counter = sorted(list(collections.Counter(A).values()),reverse=True)
    c_index = 0
    k=0
    for i in range(1,N+1):
        k+=1
        if len(counter)<i:
            print((0))
            continue
        while counter[c_index]*k > N and c_index<len(counter)-1:
            N-=counter[c_index]
            c_index+=1
            k-=1
        print((N//k))
    return

def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    solve(N, A)

if __name__ == '__main__':
    main()
# Original solution
import bisect
import sys
input = sys.stdin.readline

n = int(eval(input()))
a = [int(item) for item in input().split()]
cnt = [0] * (n + 1)
for item in a:
    cnt[item] += 1
cnt.sort()
cumsum = [0] * (n + 2)
for i in range(n+1):
    cumsum[i+1] = cumsum[i] + cnt[i]

ans = []
for i in range(n):
    if cnt[i+1] == 0:
        ans.append(0)
        continue
    l = 0; r = n+1
    while r - l > 1:
        mid = (l + r) // 2
        index = bisect.bisect_left(cnt, mid) - 1
        if index <= i:
            l = mid
            continue
        num = index - i
        if mid * num <= cumsum[index + 1]:
            l = mid
        else:
            r = mid
    ans.append(l)

ans.reverse()
print(("\n".join([str(item) for item in ans])))

# Optimized solution
import bisect
import sys
input = sys.stdin.readline

n = int(eval(input()))
a = [int(item) for item in input().split()]
cnt = [0] * (n + 1)
for item in a:
    cnt[item] += 1
cnt.sort()
cumsum = [0] * (n + 2)
for i in range(n+1):
    cumsum[i+1] = cumsum[i] + cnt[i]

indexes = [0] * (n+1)
for i in range(n+1):
    indexes[i] = bisect.bisect_left(cnt, i) - 1

ans = []
for i in range(n):
    if cnt[i+1] == 0:
        ans.append(0)
        continue
    l = 0; r = n+1
    while r - l > 1:
        mid = (l + r) // 2
        index = indexes[mid]
        if index <= i:
            l = mid
            continue
        num = index - i
        if mid * num <= cumsum[index + 1]:
            l = mid
        else:
            r = mid
    ans.append(l)

ans.reverse()
print(("\n".join([str(item) for item in ans])))
# Original solution
import collections
import heapq

def main():
    N = int(input())
    A = list(map(int, input().split()))
    # print(N, A)
    # 整数ごとに何枚あるか数える
    c = collections.Counter(A)
    v = [-x for x in c.values()]
    # print(c, v)

    _max = len(v)
    ans = [N]
    for K in range(2, N+1):
        # Kがカードの種類より大きい場合は1回も食べれない
        if K > _max:
            ans.append(0)
            continue
        q = v[:]
        heapq.heapify(q)

        cnt = 0
        while len(q) >= K:
            eat = []
            # 枚数の多い順にK個取り出す
            for k in range(K):
                eat.append(heapq.heappop(q))
            cnt += 1
            for e in eat:
                if e < -1:
                    heapq.heappush(q, e + 1)
        ans.append(cnt)
    
    print(*ans, sep='\n')

if __name__ == '__main__':
    main()


# Optimized solution
def main():
    N = int(input())
    A = list(map(int, input().split()))

    # C[x]: 書かれている整数がxであるカードの枚数
    C = [0] * (N + 1)
    D = [0] * (N + 1)
    for a in A:
        C[a] += 1
        D[C[a]] += 1

    # AからK(1<=K<=N)枚ずつカードを抜いてったときに、
    # x回以上抜くことができるか判定する。
    # 抜くことができると判定されたxの最大値が答えになる。

    # 例えば、A = [1 1 1 1 1 2 2 3] とする。
    # -> C = [5 2 1 0 0 0 0 0]
    # ここから2枚ずつカードを抜ける回数を考えるとき、
    # 「3回抜く」とすると、数字の1は、どうやっても2個は絶対余る
    # そこで、絶対余る部分を捨ててCを作り直す(=Eとする)と、
    # E = [3 2 1 0 0 0 0 0]
    # ここから2枚ずつ3回抜けるか判定するなら、
    # sum(E) >= 2 * 3 = 6
    # であるか見ればよい。今回の場合ちょうど6なので、2枚ずつ3回は抜ける。
    
    # 3枚ずつ2回ぬけるか調べる場合、
    # E = [2 2 1] となり、sum(E) = 5 < 3 * 2 = 6 なので、抜けないことが分かる

    # よって、
    # sum(min(C[i], x)) >= K * x であれば抜くことができる
    # S(x) = sum(min(C[i], x)) とすると、
    # S(x) = S(x-1) + [Cの中でC[i] >= x であるものの個数]
    # となることから、Cの中でC[i] >= x であるものの個数 = D(x) とすると、
    # S(x) = sum_(1~x) D(i) となる。
    # つまり、S(x)は、D(x) を最初に全部計算しておいて、累積和をとることで高速に計算できる。

    # S(x) >= K * x となるxの最大値を、kを1からNまで動かして見つければよい。
    # ここで、xを左辺にもっていって、
    # S(x) / x >= Kとなるxの最大値を見つけるようにする。
    # また、S(x) / x = f(x) とおく。

    # 最大値を見つけるために2分探索してもいいが、
    # Kが増えると、答えは以前の値以下になるはずなので、
    # K+1のとき、Kでの答えの位置から0へと探索していけば、O(N)で答えが見つかる
    S = [0] * (N + 1)
    f = [0] * (N + 1)
    for x in range(1, N+1):
        S[x] = S[x-1] + D[x]
        f[x] = S[x] // x

    ans = []
    prev_ans = N
    for K in range(1, N+1):
        a = prev_ans
        while True:
            if f[a] >= K or a == 0:
                break
            a -= 1
        ans.append(a)
        prev_ans = a

    print(*ans, sep='\n')

if __name__ == '__main__':
    main()
# Original solution
from sys import stdout
printn = lambda x: stdout.write(x)
inn = lambda : int(eval(input()))
inl   = lambda: list(map(int, input().split()))
inm   = lambda:      list(map(int, input().split())) 
DBG = True # and False
BIG = 999999999
R = 10**9 + 7

def ddprint(x):
  if DBG:
    print(x)

def f(k,p):
  acc = n 
  for i in range(len(b)):
    if b[i]>p:
      acc -= b[i]-p 
    else:
      break
  return (acc >= k*p)

n = inn()
a = inl()
h = {}
for x in a:
  if x in h:
    h[x] += 1
  else:
    h[x] = 1
b = []
for x in h:
  b.append(h[x])
b.sort(reverse=True)

#ddprint(b)

for k in range(1,n+1):
  mn = 0
  mx = n//k + 1
  while mx > mn+1:
    mid = (mn+mx)//2
    if f(k,mid):
      mn = mid 
    else:
      mx = mid 
  print(mn)


# Optimized solution
from sys import stdout
printn = lambda x: stdout.write(x)
inn = lambda : int(eval(input()))
inl   = lambda: list(map(int, input().split()))
inm   = lambda:      list(map(int, input().split())) 
DBG = True # and False
BIG = 999999999
R = 10**9 + 7

def ddprint(x):
  if DBG:
    print(x)

def f(k,p):
  return (c[p] >= k*p)

def ff(k,p):
  acc = n 
  for i in range(len(b)):
    if b[i]>p:
      acc -= b[i]-p 
    else:
      break
  return (acc >= k*p)

n = inn()
a = inl()
h = {}
for x in a:
  if x in h:
    h[x] += 1
  else:
    h[x] = 1
b = []
for x in h:
  b.append(h[x])
b.sort(reverse=True)

#ddprint(b)

c = [0]*(n+1)
for p in range(1,n+1):
  acc = n 
  for i in range(len(b)):
    if b[i]>p:
      acc -= b[i]-p 
    else:
      break
  c[p] = acc


for k in range(1,n+1):
  mn = 0
  mx = n//k + 1
  while mx > mn+1:
    mid = (mn+mx)//2
    if f(k,mid):
      mn = mid 
    else:
      mx = mid 
  print(mn)
# Original solution
N = int(eval(input()))
A = list(map(int, input().split()))
types = {}
for i in A: types[i] = types.get(i, 0) + 1
A = sorted([types[k] for k in types], reverse=True)
L = len(A)
cumsum = [0 for i in range(L+1)]
for i in range(L-1, -1, -1):
    cumsum[i] = A[i] + cumsum[i+1]

# Highest K for given O
def calc(O):
    def getMidPoint(lo, hi):
        if lo >= hi: return lo
        mid = lo + (hi - lo+1) // 2
        if A[mid] > O:
            return getMidPoint(mid, hi)
        else:
            return getMidPoint(lo, mid-1)

    mid = getMidPoint(0, L-1)
    if A[mid] < O: mid = - 1
    return (mid+1) + cumsum[mid+1] // O

for K in range(1, N+1):
    def getO(lo, hi):
        if lo >= hi: return lo
        mid = lo + (hi - lo+1) // 2
        if calc(mid) < K:
            return getO(lo, mid - 1)
        else:
            return getO(mid, hi)
        
    print((getO(0, N)))

# Optimized solution
N = int(eval(input()))
A = list(map(int, input().split()))
types = {}
for i in A: types[i] = types.get(i, 0) + 1
A = sorted([types[k] for k in types], reverse=True)
L = len(A)
cumsum = [0 for i in range(L+1)]
for i in range(L-1, -1, -1):
    cumsum[i] = A[i] + cumsum[i+1]



def getMidPoint(lo, hi, O):
    if lo >= hi: return lo
    mid = lo + (hi - lo+1) // 2
    if A[mid] > O:
        return getMidPoint(mid, hi, O)
    else:
        return getMidPoint(lo, mid-1, O)

getMid = [getMidPoint(0, L - 1, o) for o in range(N+1)]

# Highest K for given O
def calc(O):
    

    mid = getMid[O]
    if A[mid] < O: mid = - 1
    return (mid+1) + cumsum[mid+1] // O

for K in range(1, N+1):
    def getO(lo, hi):
        if lo >= hi: return lo
        mid = lo + (hi - lo+1) // 2
        if calc(mid) < K:
            return getO(lo, mid - 1)
        else:
            return getO(mid, hi)
        
    print((getO(0, N)))
# Original solution
from collections import Counter
from itertools import accumulate
import bisect

n = int(eval(input()))
a = list(map(int, input().split()))
b = sorted(Counter(a).values())
b = [0]*(n-len(b))+b
c = list(accumulate([0]+b))

for k in range(1,n+1):
    l = 0
    r = n+1
    while r-l>1:
        x = (r+l)//2
        i = bisect.bisect_left(b,x)
        if c[i]+(n-i)*x>=x*k:
            l = x
        else:
            r = x
    print(l)




# Optimized solution
from collections import Counter
from itertools import accumulate
import bisect

n = int(eval(input()))
a = list(map(int, input().split()))
b = sorted(Counter(a).values())
exist = len(b)
b = [0]*(n-exist)+b
c = list(accumulate([0]+b))

print(n)
for k in range(2,n//2+1):
    l = 0
    r = n+1
    while r-l>1:
        x = (r+l)//2
        i = bisect.bisect_left(b,x)
        if c[i]+(n-i)*x>=x*k:
            l = x
        else:
            r = x
    print(l)

for k in range(max(n//2+1,2),n+1):
    if exist>=k:
        print((1))
    else:
        print((0))
# Original solution
from collections import Counter
from itertools import accumulate
import bisect

printRows = lambda x:print('\n'.join(map(str,x)))

n = int(input())
a = list(map(int, input().split()))
b = sorted(Counter(a).values())
exist = len(b)
b = [0]*(n-exist)+b
c = list(accumulate([0]+b))

ans = [n]
for k in range(2,n+1):
    l = 0
    r = n//k+1
    while r-l>1:
        x = (r+l)//2
        i = bisect.bisect_left(b,x)
        if c[i]+(n-i)*x>=x*k:
            l = x
        else:
            r = x
    ans.append(l)

printRows(ans)


# Optimized solution
from collections import Counter
from itertools import accumulate
import bisect

printRows = lambda x:print('\n'.join(map(str,x)))

n = int(input())
a = list(map(int, input().split()))
b = sorted(Counter(a).values())
exist = len(b)
b = [0]*(n-exist)+b
c = list(accumulate([0]+b))

ans = [n]
for k in range(2,exist+1):
    l = 0
    r = n//k+1
    while r-l>1:
        x = (r+l)//2
        i = bisect.bisect_left(b,x)
        if c[i]+(n-i)*x>=x*k:
            l = x
        else:
            r = x
    ans.append(l)

printRows(ans+[0]*(n-exist))
# Original solution
from collections import Counter
from itertools import accumulate
import bisect

printRows = lambda x:print('\n'.join(map(str,x)))

n = int(input())
a = list(map(int, input().split()))
b = sorted(Counter(a).values())
exist = len(b)
b = [0]*(n-exist)+b
c = list(accumulate([0]+b))

ans = [n]
for k in range(2,exist+1):
    l = 0
    r = n//k+1
    while r-l>1:
        x = (r+l)//2
        i = bisect.bisect_left(b,x)
        if c[i]+(n-i)*x>=x*k:
            l = x
        else:
            r = x
    ans.append(l)

printRows(ans+[0]*(n-exist))


# Optimized solution
import sys

readline = sys.stdin.buffer.readline
sys.setrecursionlimit(10**7)
def readstr():return readline().rstrip().decode()
def readstrs():return list(readline().decode().split())
def readint():return int(readline())
def readints():return list(map(int,readline().split()))
def printrows(x):print(('\n'.join(map(str,x))))

from collections import Counter
from itertools import accumulate
import bisect

n = readint()
a = readints()
b = sorted(Counter(a).values())
exist = len(b)
b = [0]*(n-exist)+b
c = list(accumulate([0]+b))

ans = [n]
for k in range(2,exist+1):
    l = 0
    r = n//k+1
    while r-l>1:
        x = (r+l)//2
        i = bisect.bisect_left(b,x)
        if c[i]+(n-i)*x>=x*k:
            l = x
        else:
            r = x
    ans.append(l)

printrows(ans+[0]*(n-exist))
# Original solution
from bisect import bisect_left

N = int(eval(input()))
A = list(map(int, input().split()))

lst = [0] * (N + 1)
for a in A:
    lst[a - 1] += 1
lst.sort() #頻度列

s = [0] * (N + 1)
for i in range(N):
    s[i + 1] = s[i] + lst[i + 1]

# print (lst)
# print (s)

def check(x, k):
    i = bisect_left(lst, x) - 1
    total = x * (N - i) + s[i]
    return total >= x * k


for k in range(1, N + 1):
    l = 0 #OK
    r = N // k + 1 #NG
    while l + 1 < r:
        c = (l + r) // 2
        if check(c, k):
            l = c
        else:
            r = c
    print (l)
        

# Optimized solution
from bisect import bisect_left

N = int(eval(input()))
A = list(map(int, input().split()))

lst = [0] * (N + 1)
for a in A:
    lst[a - 1] += 1
lst.sort() #頻度列

s = [0] * (N + 1)
for i in range(N):
    s[i + 1] = s[i] + lst[i + 1]

# print (lst)
# print (s)

def check(x, k):
    i = bisect_left(lst, x) - 1
    total = x * (N - i) + s[i]
    return total >= x * k

ans = N
for k in range(1, N + 1):
    while True:
        if check(ans, k):
            break
        ans -= 1
    print (ans)
# Original solution
n=int(eval(input()))
a=[int(j) for j in input().split()]
from collections import Counter
c=Counter(a)
l=c.most_common()
ll=[]
for i,j in l:
    ll.append(-j)

import heapq
import copy
for k in range(1,1+n):
    if k==1:
        print(n)
    else:
        ans=0
        q=copy.deepcopy(ll)
        heapq.heapify(q)
        while True:
            if len(q)<k:
                break
            t=[]
            for i in range(k):
                t.append(-heapq.heappop(q))
            m=min(t)
            ans+=m
            for i in t:
                if i-m!=0:
                    heapq.heappush(q,-(i-m))
        print(ans)



# Optimized solution
import sys
input = sys.stdin.readline
n=int(eval(input()))
a=[int(j) for j in input().split()]
from collections import Counter
c=Counter(a)
l=c.most_common()
ll=[]
for i,j in l:
    ll.append(j)
ll.sort()
s=sum(ll)
rem=0
for k in range(1,n+1):
    rest=k-rem
    while ll and ll[-1]>s//rest:
        s-=ll[-1]
        ll.pop()
        rem+=1
        rest-=1
    print((s//rest))
# Original solution
import sys
from collections import Counter
from bisect import bisect_left

sys.setrecursionlimit(10 ** 6)
input = sys.stdin.readline

class BitSum:
    def __init__(self, n):
        self.n = n
        self.table = [0] * (n + 1)

    def update(self, i, x):
        i += 1
        while i <= self.n:
            self.table[i] += x
            i += i & -i

    def sum(self, i):
        i += 1
        res = 0
        while i > 0:
            res += self.table[i]
            i -= i & -i
        return res

def main():
    n = int(eval(input()))
    aa = list(map(int, input().split()))
    aa = list(Counter(aa).values())
    aa.sort()
    bit = BitSum(len(aa))
    for i, a in enumerate(aa):
        bit.update(i, a)
    # print(aa)
    l = n + 1
    pi=len(aa)
    for k in range(1, n + 1):
        r = l + 1
        l = 0
        while l + 1 < r:
            m = (l + r) // 2
            i = bisect_left(aa[:pi + 1], m)
            s = bit.sum(i - 1) + m * (len(aa) - i)
            if s >= m * k:
                l = m
            else:
                r = m
        pi = i
        print(l)

main()


# Optimized solution
import sys
from collections import Counter

sys.setrecursionlimit(10 ** 6)
input = sys.stdin.readline

def main():
    n = int(eval(input()))
    aa = list(map(int, input().split()))
    aa = list(Counter(aa).values())
    aa.sort()
    cs = [0]
    s = 0
    for a in aa:
        s += a
        cs += [s]
    # print(aa)
    # print(cs)
    ans = n + 1
    i = len(aa)
    for k in range(1, n + 1):
        while 1:
            while i > 0 and aa[i - 1] >= ans:
                i -= 1
            s = cs[i] + ans * (len(aa) - i)
            if s >= ans * k:
                break
            else:
                ans -= 1
        print(ans)

main()
# Original solution
import copy
import bisect

N = int(eval(input()))
A = list(map(int, input().split()))
C = [0]*(N + 1)
for a in A:
    C[a] += 1
sorted_C = sorted(C)

def h(L, i):
    """
    sorted_C[N - i : N]の最小の所に、sorted_C[ : N - i]を順番に積み上げるイメージ
    """
    if i == 1:
        return N
    
    if i > N//2:
        if L[N - i + 1] == 0:
            return 0
        else:
            return 1
    
    for j in range(N - i, 0, - 1):
        if L[j] == 0:
            return L[N - i + 1]
        
        L[N - i + 1] += L[j]
        a = bisect.bisect_right(L[N - i + 2: ], L[N - i + 1])
        L[N - i + 1:] = L[N - i + 2: N - i + 2 + a] + [L[N - i + 1]] + L[N - i + 2 + a :]
        # L[i -1]が大きくなったからソートし直す
        # これはL[0 : i - 2]はソート済みだからbisectでL[0 : i - 2]にL[i - 1]が入るいちを見つければ良い。下の解答参照
    return L[N - i + 1]
        
for i in range(N):
    L = copy.copy(sorted_C)
    print((h(L, i + 1)))

# Optimized solution
N = int(eval(input()))
A = list(map(int, input().split()))
C = [0]*N
for a in A:
    C[a - 1] += 1
D = [0]*(N + 1)
for c in C:
    D[c] += 1

Dk_accum = [0]*(N + 1)
for i in range(1, N + 1):
    Dk_accum[i] = Dk_accum[i - 1] + i*D[i]
    
D_sum = sum(D)
D_accum = [0]*(N + 2)
D_accum[0] = D_sum
for i in range(1, N + 1):
    D_accum[i] = D_accum[i - 1] - D[i - 1]
    
F = [0]*(N + 1)
for i in range(1, N + 1):
    F[i] = (Dk_accum[i]//i + D_accum[i + 1])

i = N
for K in range(1, N + 1):
    while i > 0 and K > F[i]:
        i -= 1
    print(i)