#include<bits/stdc++.h>
using namespace std;
const int N=3210,inf=1e9+10;
int n,mid;
struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int w,int f) : from(u), to(v), cap(w), flow(f) {}
};
vector<int> G[N];
vector<Edge> edge;
int dep[N],cur[N],cnt,k,fa[N];
void add(int u,int v,int w)
{
edge.push_back(Edge(u,v,w,0));
edge.push_back(Edge(v,u,0,0));
k=edge.size();
G[u].push_back(k-2);
G[v].push_back(k-1);
}
void init(){
for(int i=0; i<N; ++i) {
G[i].clear();
}
edge.clear();
}
bool vis[N];
bool bfs()
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(0);
vis[0]=1;
dep[0]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<G[x].size();++i)
{
Edge& e=edge[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
dep[e.to]=dep[x]+1;
q.push(e.to);
}
}
}
return vis[2*mid+1];
}
int dfs(int x,int a)
{
if(x==(2*mid+1)||a==0)
{
return a;
}
int flow=0,f;
for(int& i=cur[x];i<G[x].size();++i)
{
Edge& e=edge[G[x][i]];
if(dep[e.to]==dep[x]+1&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
{
e.flow+=f;
edge[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0)
{
break;
}
}
}
return flow;
}
int find(int x)
{
if(fa[x]==x)
{
return x;
}
else
{
return find(fa[x]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=3200;++i)
{
fa[i]=i;
}
int l=1,r=1600;
while(l<r)
{
init();
mid=(l+r+1)>>1;
for(int i=1;i<=mid;++i)
{
add(0,i,1);
add(i+mid,2*mid+1,1);
}
for(int i=2;i*i<2*mid;++i)
{
for(int j=max(1,i*i-mid);j<i*i-j;++j)
{
if(i*i-j<=mid)
{
add(j,i*i-j+mid,1);
}
}
}
int flow=0;
while(bfs())
{
// cout<<"1";
memset(cur,0,sizeof(cur));
flow+=dfs(0,inf);
}
// cout<<flow<<endl;
if(mid-flow<=n)
{
l=mid;
}
else
{
r=mid-1;
}
if(l==r)
{
break;
}//cout<<mid<<" "<<l<<" "<<r<<endl;
}
init();
mid=(l+r)>>1;
for(int i=1;i<=mid;++i)
{
add(0,i,1);
add(i+mid,2*mid+1,1);
}
for(int i=2;i*i<2*mid;++i)
{
for(int j=max(1,i*i-mid);j<i*i-j;++j)
{
if(i*i-j<=mid)
{
add(j,i*i-j+mid,1);
}
}
}
int flow=0;
while(bfs())
{
// cout<<"1";
memset(cur,0,sizeof(cur));
flow+=dfs(0,inf);
}
if(mid-flow<=n)
{
printf("%d\n",mid);
}
for(int i=1;i<=mid;++i)
{
for(int j=0;j<G[i].size();++j)
{
if(edge[G[i][j]].flow==1&&edge[G[i][j]].to<=2*mid)
{
fa[edge[G[i][j]].to-mid]=find(i);
}
}
}
for(int i=1;i<=mid;++i)
{
if(find(i)==i)
{
for(int j=1;j<=mid;++j)
{
if(find(j)==i)
{
printf("%d ",j);
}
}
cout<<endl;
}
}
return 0;
}
我样例没过,交上去却对了,真奇怪