#include <iostream>
#include <fstream>
#include <deque>
using namespace std;
const int nmax=75005;
deque<int> d;
int dp[2][nmax],f1[nmax],f2[nmax];
int ap[205],opt[205];
int use,n,G,i,ans,x,j;
void recu(int lin,int zr,int cat)
{
for(int i=zr; i<=cat; i++)
dp[use][i]=(1<<30)-1;
for(int rest=0; rest<min(lin,cat-zr+1); rest++)
{
d.clear();
for(int i=zr+rest; i<=cat; i+=lin)
{
if((!d.empty())&&i-d.front()>lin*ap[lin])
d.pop_front();
while((!d.empty())&&dp[1-use][i]-(i-rest)/lin<=dp[1-use][d.back()]-(d.back()-rest)/lin)
d.pop_back();
d.push_back(i);
dp[use][i]=(i-d.front())/lin+dp[1-use][d.front()];
}
}
use=1-use;
}
void get_best(int l,int r,int zr,int cat)
{
for(int i=zr;i<=cat;i++)
dp[0][i]=(1<<30)-1;
dp[0][zr]=0;
use=1;
for(int lin=l;lin<=r;lin++)
recu(lin,zr,cat);
for(int i=zr;i<=cat;i++)
f1[i]=dp[1-use][i];
}
void get_best_rev(int l,int r,int zr,int cat)
{
for(int i=zr;i<=cat;i++)
dp[0][i]=(1<<30)-1;
dp[0][zr]=0;
use=1;
for(int lin=r;lin>=l;lin--)
recu(lin,zr,cat);
for(int i=zr;i<=cat;i++)
f2[i]=dp[1-use][i];
}
void divide(int l,int r,int ost,int odr,int expected)
{
int m=(l+r)/2;
if(l>r)
return;
if(l==r)
{
opt[m]=odr;
return;
}
get_best(l,m,0,odr-ost);
get_best_rev(m+1,r,0,odr-ost);
for(int i=0;i<=odr-ost;i++)
{
if(f1[i]+f2[odr-ost-i]==expected)
opt[m]=i+ost;
}
int v1=f1[opt[m]-ost],v2=f2[odr-opt[m]];
divide(l,m,ost,opt[m],v1);
divide(m+1,r,opt[m],odr,v2);
}
int main()
{
ifstream f("ghiozdan.in");
ofstream g("ghiozdan.out");
f>>n>>G;
for(i=1;i<=n;i++)
{
f>>x;
ap[x]+=1;
}
get_best(1,200,0,G);
for(i=1;i<=G;i++)
if(dp[use][i]<=n)
ans=i;
g<<ans<<' '<<dp[use][ans]<<'\n';
divide(1,200,0,ans,dp[use][ans]);
for(i=1;i<=200;i++)
for(j=opt[i-1]+i;j<=opt[i];j+=i)
g<<i<<'\n';
return 0;
}