CF909F AND-permutations 构造
正解:构造
解题报告:
QAQ我jio得还挺难的,,,构造+数论什么的果然还是不适合灵巧这种菜菜啊QAQ
不过理解了的话也就没有那么难?所以还是港下QAQ
首先看task1
首先要发现一个,必然的结论
就是当n为奇数时是无解的
因为你这么想,只看20那一位,当n是奇数时,令n=2*k+1,那就有k+1个1和k个0,然而我构造出来又是需要k+1个0和k个1的,所以显然布星
然后关于构造,说实话我jio得这种要构造出一个范围内的全排列的大多是用交换解决的?
这个同样,就是找出小于等于n的max(2k)然后交换2k和2k-1 2k+1和2k-2 ... n和2*2k-1-n
这样2*2k-1-n到n就解决了
剩下的其实都是一样的方法解决掉嘛,能get?
然后task1就解决辣!
task2一样的思路想下,就是先解决什么时候无解然后想下怎么交换就做完了嘛
首先关于无解
显然的是当n=1<<k时无解,因为对于n你显然找不到一个数使得它们并起来!=0嘛
然后当n=3或者n=5时也无解(,,,这个我也说不清原理?QAQ?反正手玩出来就是无解的,,,但我不会求QAQ
然后这么考虑,把2k和2k+1分一组,显然它们只有20这一位不同,那就显然会并起来!=0
然后分类讨论下
如果n是偶数
这个情况比较简单,这时候就剩下1和n,而且因为n!=1<<k所以显然n&(n-2)!=0
所以把第一个和倒数三个变成 n-1 n 1 n-2 构造完毕
那如果n是奇数
这个构造起来就奇妙一些,,,就是说你告诉我这么构造我能理解,但是我是想不出来要这么构造的QAQ
就这样子 前7个变成7326145
然后因为n是奇数所以没有剩,完美结束辣!
欧克克我去打代码了等下把code放上来QAQ
#include<bits/stdc++.h> using namespace std; #define ll long long #define rp(i,x,y) for(register ll i=x;i<=y;++i) #define my(i,x,y) for(register ll i=x;i>=y;--i) const ll N=1000000+10; ll n,cnt,as[N]; inline ll read() { register char ch=getchar();register ll x=0;register bool y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar(); if(ch=='-')ch=getchar(),y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar(); return y?x:-x; } inline ll lg(ll x) { ll d=0; while((1<<d)<=x)++d; return d-1; } inline void tsk1(ll x) { if(x&1){printf("NO\n");return;} printf("YES\n"); ll cs=(ll)lg(x),nw=n,gg;cnt=0; while(nw>0) {gg=1<<cs;my(i,nw,gg)as[++cnt]=(gg<<1)-1-i;rp(i,gg,nw)as[++cnt]=i;nw=(gg<<1)-2-nw;cs=(ll)lg(nw);} my(i,n,1)printf("%lld ",as[i]); printf("\n"); } inline void tsk2(ll x) { if(x==3 || x==5 || x==(1<<lg(x))){printf("NO\n");return;} printf("YES\n");cnt=1; if(x&1){cnt=7;as[1]=7;as[2]=3;as[3]=2;as[4]=6;as[5]=1;as[6]=4;as[7]=5;} while(cnt<=x){++cnt;as[cnt]=cnt+1;++cnt;as[cnt]=cnt-1;} if(!(x&1)){as[1]=x-1;as[x-2]=x;as[x-1]=1;as[x]=x-2;} rp(i,1,n)printf("%lld ",as[i]); } int main() { n=read(); tsk1(n);tsk2(n); return 0; }