#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N=1e4+10;
//定义全局变量
char collect[N];//用于存储集合中的每一个元素
char table[N][N];//用于存储集合进行*运算的运算表中的数据
char inverse[N];//用于存放含有逆元的集合元素
/*
* 验证封闭性的函数
* n表示的是集合S中的元素的个数,A数组存储的是集合中的元素,result数组存储的是运算表中的数值
*/
bool fengbi(int n,char A[],char result[][N])
{
int i,j,k;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
int flag=0;
for(k=0;k<n;k++)
{
if(result[i][j]==A[k])
flag=1;
}
if(flag==0)
return false;
}
}
return true;
}
//验证集合的结合律
bool jiehe(int n,char A[],char result[][N])
{
int i,j,k;
int a;
int first = 0,second = 0;
//如果代数系统封闭就可以开始验证结合律的性质
if(fengbi(n,A,result))
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
for(k=0;k<n;k++)
{
if(i!=j&&j!=k)
{
for(a=0;a<n;a++)
{
if(result[i][j]==A[a])//(a*b)*c中a*b;
{
first=a;
}
if(result[j][k]==A[a])//a*(b*c)中b*c;
{
second=a;
}
}
//如果前面(a*b)*c!=a*(b*c)就返回false
if(result[first][k]!=result[i][second])
return false;
}
}
}
}
return true;
}
return false;
}
//验证代数系统是否含有幺元
int yaoyuan(int n,char A[],char result[][N])
{
/*
* 按照行来依次对每一列的数据进行运算表的判别,观察列头元素是否与运算表中的数据相同。
* 若相同,即sum++;若相同就返回集合中的第几个元素的序号。(根据集合的幺元是唯一的即可直接返回)
*/
int i,j;
int sum=0;
for(i=0;i<n;i++)
{
sum=0;
for(j=0;j<n;j++)
{
if(result[i][j]==A[j]&&result[j][i]==A[j])
sum+=1;
}
if(sum==n)
{
return i+1;
}
}
return 0;
}
/*
* 验证代数系统中是否有零元
* 零元在代数系统表示的意思就是代数系统中的一个元素与另一个元素做*运算后的结果都为该元素。
*/
int lingyuan(int n,char A[],char result[][N])
{
int i,j;
int sum;
for(i=0;i<n;i++)
{
sum=0;
for(j=0;j<n;j++)
{
if(result[i][j]==A[i]&&result[j][i]==A[i])
sum+=1;
}
if(sum==n)
{
return i+1;
}
}
return 0;
}
/*
* 函数用于验证代数系统中是否含有逆元*/
int niyuan(int n,char A[],char result[][N])
{
int sum;
int data= collect[yaoyuan(n,A,result)-1];//用来存储相应的幺元数值
if(data){
sum=0;
for(int u=0;u<n;u++)
{
for(int h=0;h<n;h++){
if(result[u][h]==data){
inverse[sum++]=collect[u];
}
if(result[h][u]==data){
inverse[sum++]=collect[h];
}
}
}
int flag=0;//该变量用于记录在集合中的元素是否全部含有逆元
for(int u=0;u<n;u++)
{
int link=0;
for(int h=0;h<sum;h++){
if(inverse[h]==collect[u]){
link++;
}
}
if(link==2){
flag++;
}
}
if(flag==n) return 1;//如果集合中任意元素都含有逆元,则返回真
}
return 0;
}
/*
* 函数用于验证代数系统是否具有交换律*/
bool jiaohuan(int n,char A[],char result[][N])
{
for(int u=0;u<n;u++)
{
for(int h=0;h<n;h++)
{
if(result[u][h]!=result[h][u])
return false;
}
}
return true;
}
/*
* 函数用于验证代数系统的性质是否成立*/
void judge(int n, char A[], char result[][N])
{
if(fengbi(n,A,result))
cout<<"运算具有封闭性"<<endl;
if(jiehe(n,A,result))
cout<<"运算具有结合律"<<endl;
if(yaoyuan(n,A,result))
cout<<"运算有幺元"<<endl;
if(lingyuan(n,A,result))
cout<<"运算有零元"<<endl;
if(niyuan(n,A,result))
cout<<"运算有逆元"<<endl;
if(jiaohuan(n,A,result))
cout<<"运算有交换律"<<endl;
}
/*
* 函数用于找出生成元的n阶运算后
* 的元素在集合A[]中的元素下标*/
int position(int n,char A[],int e)
{
int i;
for(i=0;i<n;i++)
{
if(e==A[i])
return i;
}
return n+1;
}
/*
* 函数用于判断数组是否相同
* 即判断生成元的n阶元素是否
* 全部包含了集合A[]中的元素*/
int equivalence(int n,char A[],vector<int> B)
{
int i,j;
int sum=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(B[i]==A[j])
{
sum+=1;
}
}
}
if(sum==n)
return 1;
else
return 0;
}
/*
* 函数用于判断代数系统中是否含有生成元*/
int shengchengyuan(int n,char A[],char result[][N])
{
int flag=0;//定义一个信号量
for(int u=0;u<n;u++){
int p=A[u];
int i=u;//用于存储生成元在集合A[]中的元素下标
vector<int> B;//用于存储生成元做n阶运算的结果
B.push_back(p);
for(int h=2;h<=n;h++){
B.push_back(result[i][u]);
i= position(n,A,result[i][u]);
flag=0;
for(int p=0;p<h-1;p++){
if(B[h-1]==B[p]){
flag=1;
break;
}
}
if(flag==1) break;
}
if(flag==0){
if(equivalence(n,A,B)){
return u+1;
}
}
}
return 0;
}
/*
* 函数用于判断代数系统是否为群或者其他类型的群*/
void SystemType(int n,char A[], char result[][N])
{
if(fengbi(n,A,result)){
cout<<"代数系统是广群"<<endl;
if(jiehe(n,A,result)){
cout<<"代数系统是半群"<<endl;
if(yaoyuan(n,A,result)) {
int yy_data = yaoyuan(n,A,result);
cout << "代数系统是独异点" << endl;
cout<<"代数系统的幺元是:"<<collect[yy_data-1]<<endl;
if (niyuan(n, A, result)) {
cout << "代数系统是群" << endl;
if (jiaohuan(n, A, result)) {
cout << "代数系统是交换群/阿贝尔群" << endl;
}
if (shengchengyuan(n, A, result)) {
int scy_data= shengchengyuan(n,A,result);
cout << "代数系统是循环群" << endl;
cout <<"生成元为:" <<A[scy_data-1]<< endl;
}
}
}
}
}
}
/*
* 函数用于将按空格分割的字符串进行处理,
* 主要处理的是集合collect数组*/
void String_To_Char_collect(string S)
{
int all=0;
for(int u=0;u<S.length();u++){
if(S[u]!=' '){
collect[all++] = S[u];
}
}
}
/*
* 函数用于将按空格分割的字符串进行处理,
* 主要处理的是运算表table数组*/
void String_To_Char_table(string S,int a)
{
int all=0;
for(int u=0;u<S.length();u++)
{
if(S[u]!=' '){
table[a][all++]=S[u];
}
}
}
//主函数
int main() {
int n;
cin>>n;//输入集合中元素的个数
getchar();
string s;//定义输入的字符串s
getline(cin,s);
s+=" ";
String_To_Char_collect(s);
char c;//输入运算的运算符号
cin>>c;
getchar();
for(int u=0;u<n;u++){//用于输入运算表中的数据
string ptr;
getline(cin,ptr);
String_To_Char_table(ptr,u);
}
int lingyuan_data= lingyuan(n,collect,table);
judge(n, collect, table);
SystemType(n,collect,table);
if(lingyuan_data>0)
cout<<"零元是:"<<collect[lingyuan_data-1]<<endl;
}