Be Positive
题目:

标注可见,信息提取
关注样例:
1 ————> No
2 ————> Yes ————> 1 0 (0 1)//0和1换位
3 ————> yes ————> 1 0 2 (0 1 2)//0和1换位
4 ————> No
先暴力前缀和,观察普通序列的规律
暴力代码(到12差不多就卡了)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100];
int main()
{
int n=30;
int a[41],sum[41],p=0;
for(int w=0;w<=n;w++)//枚举前n位
{
if(w%4==0)cout<<"No"<<endl;
else
{
sum[0]=0;
for(int j=0;j<w;j++)a[j]=j;//前w项
do{
//枚举
p=0;
for(int i=0;i<w;i++)
{
sum[i+1]=sum[i]^a[i];//前缀和
if(sum[i+1]==0)
{
p=1;break;
}
}
if(p==0)
{
for(int i=0;i<w;i++)cout<<a[i]<<' ';
cout<<endl;
break;
}
}while(next_permutation(a,a+w));
}
}
return 0;
}
如图,输出结果
我们发现1和4的倍数,都不行
并且这个特殊的数要和前面的数字调换位置,才能实现前缀异或和不为0的结果
其他的数 最小字典序排列就是正序排列

下面是正解
#include<iostream>
#include<cstdio>
using namespace std;
int a[1000010];
int main()
{
int t,n;
for(int i=0;i<1000010;i++)
{
a[i]=i;
if(i==1||i%4==0)swap(a[i],a[i-1]);
}
cin>>t;
while(t--)
{
cin>>n;
if(n==1||n%4==0)cout<<"impossible"<<endl;
else
{
for(int i=0;i<n;i++)cout<<a[i]<<' ';
cout<<endl;
}
}
return 0;
}
关于位运算符
我觉得就把第一列的符号记住就行了,直接放进代码里就能用,临时不用知道他的底层逻辑
或运算用符号“||”或“+”表示//+
异或运算符号为 XOR 或 EOR 或 ⊕(编程语言中常用)//
与运算通常用符号“&”或“·”表示//&
后面粗体是编程时用的符号


浙公网安备 33010602011771号