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 或 ⊕(编程语言中常用)//
与运算通常用符号“&”或“·”表示//&
后面粗体是编程时用的符号

posted @ 2025-05-15 21:35  Granya  阅读(24)  评论(0)    收藏  举报