题目链接:https://vjudge.net/contest/269300#problem/A
解题思路:
很容易想到当n是2^k的时候,可以倍增的构造出来(保证构造出来的数组从小到大)。
如果a的前2^(k-1)和b的前2^(k-1)已经可以构造相同了,那么a的后2^(k-1)个数就构造成b前2^(k-1)的对应数+2^k,b后2^(k-1)由a的前2^(k-1)构造,那么由于是前面一半的是都加上2^k所保证了a后一半里面的两两之和可以在b后一半两两和里对应。还有一个问题是前面一半取一个和后面一半取一个的情况,由构造的特殊性可以看出a构造的n个数和b构造的n个数正好可以组成1-2*n连续的数,
如果把a的后一半每个数减去2^k,把b的后一半每个数都减去2^k,那么这两个集合就是一样的了,在对应两个位置取两个数两个数组的数刚好相反,所以让后面的数加上2^k使得他们不一样但和还是一样的。
所以n!=2^k自然是无解的
#include<bits/stdc++.h>
using namespace std;
int a[2010],b[2010];
int main(){
int n;
freopen("analogous.in","r",stdin);
freopen("analogous.out","w",stdout);
a[0] = 1,a[1] = 4;
b[0] = 2,b[1] = 3;
for(int i = 2; i <= 512; i<<=1){
for(int j = 0; j < i; j++){
a[i+j] = b[j]+2*i;
b[i+j] = a[j]+2*i;
}
}
while(scanf("%d",&n)&&n)
{
if((n&(n-1))!=0||n==1) puts("No");
else{
puts("Yes");
for(int i = 0; i < n; i++)
printf("%d%c",a[i],i==n-1?'\n':' ');
for(int i = 0; i < n; i++)
printf("%d%c",b[i],i==n-1?'\n':' ');
}
}
return 0;
}