#include<iostream>
using namespace std;
const int SIZE = 50;
int a[SIZE][SIZE];
void copy(int n);
void tournament(int n);
bool odd(int n);
void makecopy(int n);
void copyodd(int n);
int main()
{
int n;
int i,j;
cout<<"参赛选手人数为:";
cin >> n; //输入参赛人数n
tournament(n);
if(odd(n)) // n为奇数时的输出
{
for(i = 1; i<=n; i++)
{
for(j = 1; j<=n+1; j++)
if(a[i][j] == n+1)
cout << "x ";
else
cout << a[i][j] << " " ;
cout << endl;
}
cout<<"其中第一列代表选手,第二列到第n列分别是第一天到第n天的对手!x则代表没有比赛!\n";
}
else //n为偶数时的输出
{
for(i = 1; i<=n; i++)
{
for(j = 1; j<=n; j++)
cout << a[i][j] << " " ;
cout << endl;
}
cout<<"其中第一列代表选手,第二列到第n列分别是第一天到第(n-1)天的对手!\n";
}
return 0;
}
void copy(int n) //n为偶数时的复制
{
int m = n/2;
for(int i = 1; i<=m; i++)
for(int j = 1; j<=m; j++)
{
a[i][j+m] = a[i][j] + m;
a[i+m][j] = a[i][j+m];
a[i+m][j+m] = a[i][j];
}
}
void tournament(int n)
{
if(n == 1)
{
a[1][1] = 1;
return;
}
if(n>1 && odd(n))
{
tournament(n+1);
return;
}
tournament(n/2);
makecopy(n);
}
bool odd(int n)
{
return n & 1;
}
void makecopy(int n) //makecopy 与copy算法类似,但是要区分n/2为奇数或偶数的情形
{
if(n/2 > 1 && odd(n/2))
copyodd(n);
else
copy(n);
}
void copyodd(int n) // n为奇数时的复制
{
int b[SIZE];
int m = n/2;
for(int i = 1; i<=m; i++)
{
b[i] = m+i;
b[m+i] = b[i];
}
for(i = 1; i<=m; i++)
{
for(int j=1; j<=m+1; j++)
{
if(a[i][j] > m)
{
a[i][j] = b[i];
a[m+i][j] = (b[i] + m)%n;
}
else
a[m+i][j] = a[i][j] + m;
}
for(j = 2; j<=m; j++)
{
a[i][m+j] = b[i+j-1];
a[b[i+j-1]][m+j] = i;
}
}
}