题意:
给一个数组a,构造一个b数组使得b是a的一个排列,且对于所有下标的子集(除全集和空集之外),a数组对应位置的数之和不等于b数组对应位置的数之和,若不能输出-1,保证a数组无重复数字出现
题解:
首先,由于考虑所有下标子集,在构造出一对a,b后,将下标任意重新排列,可以保证同样成立,那么我们考虑a数组的有序排列作为a数组,在最后映射回去即可
对于一个已经排序的a数组,一个可行的b是将a循环右移一位,证明如下:
数组下标从1开始,可以发现
我们考虑下标子集不包含1的情况,那么a数组对应求和肯定小于b数组
对于包含1的情况,设,由于两数组求和相同,把包含1的子集的求和转化为sum-对应子集,可以发现对于a,b数组答案仍不相等且a数组求和大于b数组
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cstring>
#define pii pair<int, int>
#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define debug puts("???");
#define br puts("")
#define ALL(x) x.begin(),x.end()
#define sc(x) scanf("%d", &x)
using namespace std;
const int mod = 1e9+7;
typedef long long LL;
const int maxn = 1e5+10;
pii a[maxn];
int n, ans[maxn];
int main(){
sc(n);
for(int i = 0; i < n; i++){
a[i].se = i; sc(a[i].fi);
}
sort(a,a+n);
for(int i = 1; i <= n; i++){
ans[a[i%n].se] = a[i-1].fi;
}
for(int i = 0; i < n; i++) printf("%d%c",ans[i]," \n"[i==n-1]);
return 0;
}