#include<stdio.h>
#include<stdlib.h>
#include<math.h>


typedef struct partitionnode
{
int m;
int numparts;
int parts[101];
} partition;
partition a;

int SubSets[8][20];
int index[8][20];
int MultiSet[100];
int n,q,rho,r;

int IsIn(int x,int s,partition a)
{
int i;
for(i=1;i<=a.parts[s];i++)
if(x==SubSets[s][i]) return(1);
return(0);
}

int searchdss(int s,int t,int M,partition a)
/*
** search one DSS with given partition
*/
{
int i,j,k,l;
int isdss,isperfect;

isdss=1;
isperfect=1;

if(s>=2)//To check M is not given to any existing element.
{
for(i=1;i<=s-1;i++)
if(IsIn(M,i,a)==1) //if M has been assigned to any existing element
if(M==n) return(0);
else
{
if(M<n-a.parts[s]+t) //M does not reach the value bound
return(searchdss(s,t,M+1,a))! ;
else return(0);
}

}
SubSets[s][t]=M;
if(s==a.numparts && t==a.parts[s]) //All elements of all subsets are given values.
{
for(i=1;i<=n;i++) MultiSet[i]=0;
for(i=1;i<=a.numparts-1;i++)
or(k=i+1;k<=a.numparts;k++)
for(j=1;j<=a.parts[i];j++)
for(l=1;l<=a.parts[k];l++)
{
MultiSet[((SubSets[i][j]-SubSets[k][l]+n)%n)]++;
MultiSet[((SubSets[k][l]-SubSets[i][j]+n)%n)]++;
}

for(i=1;i<=n-1;i++)
{
if(MultiSet[i]<rho) isdss=0;
if(isdss==0) break;
if(MultiSet[i]>rho) isperfect=0;
}

if(isdss==0)//
{
if(M!=n) return(searchdss(s,t,M+1,a));
else return(0);
}
else
{
printf("\n\nFind one DSS!\n");
printf("Subsets: \n");
for(i=1;i<=a.numparts;i++)
{
printf("{");
for(j=1;j<=a.parts[i];j++)
{
if(j==a.parts[i]) printf("%d! }\n",SubSets[i][j]);
else printf("%d,",SubSets[i][j]);!
}
}
printf("Multiset:\n{");
for(i=1;i<=n-1;i++)
{
if(i==n-1) printf("%d(%d)}\n",n-1,MultiSet[n-1]);
else printf("%d(%d),",i,MultiSet[i]);
}
if(isperfect==1) printf("This DSS is perfect!\n");
printf("\n");
return(1);
}
}
else // Not reach the last element of the last subset
{
if(t<a.parts[s])// not reach the last element of any subset
{
if(searchdss(s,t+1,M+1,a)==1) //search with next element is M+1
return(1);
else if(M<n-a.parts[s]+t) //search with current element is M+1 if it does not reache the value bound
return(searchdss(s,t,M+1,a));
else return(0); // current element has reached value bound
}
else// t=a.parts[s]:reach the last element of some subset (not the last one)
{
if(searchdss(s+1,1,2,a)==1)
return(1);
else if(M<n)
return(searchdss(s,t,M+1,a));
else return(0);
}
}
}

! int search(partition a)
/*
** search out the partition a
*/
{
int i,j,sum;

printf("r = %d = ",a.m);
for(i=1;i<=a.numparts;i++)
{
j = a.parts[i];
printf("%d",j);
if (i != a.numparts br> printf("+");
}
printf("\n");

sum=0;
for(i=1;i<=a.numparts-1;i++)
for(j=i+1;j<=a.numparts;j++)
{
sum=sum+2*a.parts[i]*a.parts[j];
}
printf("2*(Q_i * Q_j)=%d",sum);
if(sum<(n-1)*rho)
{
printf(" < %d=(n-1)*rho",(n-1)*rho);
return(0);
}

SubSets[1][1]=1;
if(a.parts[1]>1) // there are more than 2 elements in the first subset
return(searchdss(1,2,2,a));
else // there is only one element in 1st subset
return(searchdss(2,1,2,a));
}

void RecPartition(partition a, int r, int q, int N)
/*
** generate all q partitions
** recursive procedure used in other procedures
*/
{
int i;
if(q==0)
{
a.n! umparts = N;
if(search(a)==1)
{
//printf(! "Find on e!\n");
}
else printf("\nNone!\n\n");
}
else
{
for (i=r-q+1;i>=(int)ceil((r/(float)q));i--)
{
if(N==0 || N>=1 && a.parts[N]>=i)
{
a.parts[N+1] = i;
RecPartition(a,r-i,q-1,N+1);
}
}
}
}

void GenPartitions(int r, int q)
/*
** generate all partitions of r
*/
{
a.m = r;
RecPartition(a,r,q,0);
}


int main()
{

printf("n=");
scanf("%d",&n);
printf("q=");
scanf("%d",&q);
printf("rho=");
scanf("%d",&rho);

r=(int)ceil(sqrt(q*rho*(n-1)/(float)(q-1)));

GenPartitions(r,q);

return(0);
}