#include <stdio.h>
#include <gmp.h>
#include <math.h>
#include <set>
using namespace std;
#ifndef N
#define N 4
#endif
#define MAX_COUNT 10000
typedef struct sDataEntry{
mpz_t datas[N];
mpz_t nc;
sDataEntry(){
int i;
for(i=0;i<N;i++)mpz_init(datas[i]);
mpz_init(nc);
}
sDataEntry(const sDataEntry& d){
int i;
for(i=0;i<N;i++)mpz_init(datas[i]);
mpz_init(nc);
for(i=0;i<N;i++){
mpz_set(datas[i],d.datas[i]);
}
mpz_set(nc,d.nc);
}
~sDataEntry(){
int i;
for(i=0;i<N;i++)mpz_clear(datas[i]);
mpz_clear(nc);
}
void set_nc(){
int i;
mpz_t tmp;
mpz_init(tmp);
mpz_set_ui(nc,0);
for(i=0;i<N;i++){
mpz_mul(tmp,datas[i],datas[i]);
mpz_add(nc,nc,tmp);
}
mpz_clear(tmp);
}
bool operator<(const struct sDataEntry& s)const{
int i;
int c=mpz_cmp(nc,s.nc);
if(c!=0)return c<0;
for(i=N-1;i>=0;i--){
int c=mpz_cmp(datas[i],s.datas[i]);
if(c!=0)return c<0;
}
return false;
}
bool operator==(const struct sDataEntry& s)const{
int i;
for(i=N-1;i>=0;i--){
int c=mpz_cmp(datas[i],s.datas[i]);
if(c!=0)return false;
}
return true;
}
}DataEntry;
set<DataEntry> results;
DataEntry t;
int td[N];
void search_last()
{
long long mul=1LL;
long long sum=0LL;
int i;
if(td[N-3]==1)return;///No solution available
for(i=0;i<N-2;i++){
mul*=td[i];
sum+=(long long)td[i]*td[i];
}
if(mul<=2LL)return;///No solution available;
long long d=sum/(mul-2LL);
int up=(int)sqrt(d+0.01);
for(i=td[N-3];i<=up;i++){
td[N-2]=i;
long long a=sum+(long long)i*i;
long long b=mul*i;
long long c=b*b-4*a;
if(c<0)continue;
int u=(int)sqrt((double)c);
if(u*(long long)u<c)u=u+1;
if(u*(long long)u==c){///Found a solution now
if((b-u)&1)continue;///Invalid
td[N-1]=(int)((b-u)/2);
int j;
for(j=0;j<N;j++){
mpz_set_ui(t.datas[j],td[j]);
}
t.set_nc();
results.insert(t);
}
}
}
void search(int last)
{
int i;
if(last==N-2){
search_last();
return;
}
long long mul=1LL;
long long mul2;
double ub;
for(i=0;i<last;i++){
mul*=td[i];
}
if(mul>N)return;
ub=pow((double)N/(double)mul,1.0/(N-2-last))+0.01;
i=1;if(last>0)i=td[last-1];
for(;i<=(int)ub;i++){
td[last]=i;
search(last+1);
}
}
int tcount=0;
void dump(const DataEntry& d)
{
int i;
for(i=0;i<N-1;i++){
if(mpz_cmp(d.datas[i],d.datas[i+1])==0)return;
}
for(i=0;i<N;i++){
mpz_out_str(stdout,10,d.datas[i]);
printf("\t");
}
printf("\n");
}