1.实验内容
实验1.1
现有一个有n个元素的序列a=[a1,a2,⋯,an],定义这个序列的价值为1*a1+2*a2+…+n*an,空序列的价值为0。先给你一个长度为n的序列a,求a中所有子集价值的异或和,要求子集中元素的相对位置保持不变.
实验1.2
现有一个有n个元素的序列a=[a1,a2,⋯,an],定义其价值为a1⊕1+a2⊕2+…+an⊕n,给出这样一个序列,求其所有排列的价值vi的或.
2.测试结果
实验1.1
输入:
2
1 2
输出:
6
实验1.2
输入:
3
1 2 3
输出:
6
3.源代码
①实验1.1
#include<iostream>
using namespace std;
template <class T>
void sumSubset(T *array,int m,int n,bool *exist,T *arraySubset,int *S)
//数组array记录所有元素
//m为已判断是否存在的元素个数
//n为元素总个数
//数组exist记录子集是否包含某个元素
//数组ARRAY记录某个子集中的元素
//地址S用于记录异或和
{
if(m>=0&&m<n)
{
exist[m]=1; sumSubset(array,m+1,n,exist,arraySubset,S);
exist[m]=0; sumSubset(array,m+1,n,exist,arraySubset,S);
}
if(m==n) //所有exist均已赋值
{
int j=0,sum=0; //j用于计数该子集中的各元素,sum用于记录该子集的价值
for(int i=0;i<n;i++)
{
if(exist[i])
{
arraySubset[j]=array[i]; //将子集的第j项赋值为array[i]
j++;
}
}
for(int k=0;k<j;k++) sum+=arraySubset[k]*(k+1);
(*S)^=sum; //将异或和计入S
}
}
int main()
{
int n; //n为序列中元素个数
cin>>n;
int *a=new int[n];
int *b=new int[n];
bool *e=new bool[n];
int *ADD=new int(0);
for(int i=0;i<n;i++) cin>>a[i]; //输入序列
sumSubset(a,0,n,e,b,ADD);
cout<<*ADD<<endl;
delete []a;
delete []b;
delete []e;
delete []ADD;
return 0;
}
②实验1.2
#include<iostream>
using namespace std;
template <class T>
void swap(T *a,T *b) //swap函数用于交换两个变量的值
{
T temp=*a;
*a=*b;
*b=temp;
}
void Nor(int array[],int m,int n,int *S)
//数组array用于存放元素
//m为已排列元素个数
//n为总元素个数
//地址S用于记录或值
{
if(m>=0&&m<n)
for(int i=m;i<n;i++)
{
swap(array[i],array[m]); //交换第m项与后面的每一项分别得到一个排列
Nor(array,m+1,n,S);
swap(array[i],array[m]);
}
if(m==n) //已完成排列
{
int sum=0; //sum用于记录该排列的价值
for(int i=0;i<n;i++) sum+=array[i]^(i+1);
(*S)|=sum; //将或和计入S
}
}
int main()
{
int n; //n为序列中元素个数
cin>>n;
int *a=new int[n];
int *ADD=new int(0);
for(int i=0;i<n;i++) cin>>a[i]; //输入序列
Nor(a,0,n,ADD);
cout<<*ADD<<endl;
delete []a;
delete []ADD;
return 0;
}