题目:P9227 异或积
一.15分解
思路:用a数组来存序列,模拟每一次操作,用一个临时数组b来存a数组每个数的异或和,然后把b数组内的元素存入a数组,时间复杂度O(tk)。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,k,t;
long long a[500010],b[500010];
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=k;i++)
{
long long sum=0;
for(int i=1;i<=n;i++)
{
sum=0;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
sum^=a[j];
}
b[i]=sum;
}
for(int i=1;i<=n;i++) a[i]=b[i];
}
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
}
return 0;
}
这个程序已经能得15分了,在考试中有一定帮助。
二.35分解
思路,用15分解的程序,找到n和k,奇数和偶数时的情况:
1.当n是偶数时,如果k为偶数,那么a序列的元素不变,如果k为奇数,那么将a进行一次操作,在那次操作中,枚举每一个元素,用O(n)的时间计算出一个元素的异或和。
2.当n是奇数时,那么将a进行一次操作(和n是偶数,k是奇数的方式一样)。
总时间复杂度:O(t)。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,k,t;
long long a[500010],b[500010];
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
if(n%2==0)
{
if(k%2==0)
{
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
}
else
{
long long sum=0;
for(int i=1;i<=n;i++)
{
sum=0;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
sum^=a[j];
}
b[i]=sum;
}
for(int i=1;i<=n;i++) cout<<b[i]<<" ";
}
}
else
{
long long sum=0;
for(int i=1;i<=n;i++)
{
sum=0;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
sum^=a[j];
}
b[i]=sum;
}
for(int i=1;i<=n;i++) cout<<b[i]<<" ";
}
cout<<endl;
}
return 0;
}
这个解法离正解不远了。
三.满分解
思路:在35分的做法中,每次操作时间都是O(),而这里的n是小于等于的,所以是大于的,这里我们可以把时间复杂度优化到O(n)的,这里我们需要用到异或的性质。
1.0^A=A 0异或任何数A都等于A本身
2.A^A=0 任何数A异或其本身都等于0
3.异或运算满足交换律, 即A^B=B^A
4.异或运算满足结合律,即(A^B)^C=A^(B^C)
我们设x为当前a序列的每一个元素异或起来的值,并把中的求和改为求异或值,及x=,
而第i个元素的异或和为=,根据异或的第1第2第3条性质,可以得出==
=,最后的值没变,所以==。
此时对于一次操作的时间复杂度为O(n)。
总时间复杂度为O(tn)。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,k,t;
long long a[500010],b[500010];
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
if(n%2==0)
{
if(k%2==0)
{
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
}
else
{
long long sum=0;
for(int j=1;j<=n;j++)
{
sum^=a[j];
}
for(int i=1;i<=n;i++) cout<<(a[i]^sum)<<" ";
}
}
else
{
long long sum=0;
for(int j=1;j<=n;j++)
{
sum^=a[j];
}
for(int i=1;i<=n;i++) cout<<(a[i]^sum)<<" ";
}
cout<<endl;
}
return 0;
}
这道题就可以满分了。
---创作不易,请大家点个赞---