Codeforces 891B Gluttony 构造

来源:互联网 发布:javascript json 编辑:程序博客网 时间:2024/05/16 03:48

题意

给你一个数组a,满足a中元素两两不同。要求构造一个数组b,使得b是a的一个排列,且满足对于S={1,2,...,n}的任意一个非空真子集S={x1,x2,...,xk},有$这里写图片描述
1 ≤ n ≤ 22,0 ≤ ai ≤ 10^9

分析

比赛的时候被这个数据范围吓到了,以为是状压之类的奇奇怪怪的做法,于是就没有去猜结论。
实际上,我们把a排序后,让a整体往前移一位,然后把a[1]放到a[n],从而得到b,可以保证这样的b一定是满足条件的。
证明:对于集合S={x1,x2,...,xk},若n不在S中,则必然有i=1kbxi>i=1kaxi
反之,则设S’为S的补集,有S={y1,y2,...,ynk},不难发现有i=1nkbyi>i=1nkayi,从而有i=1kbxi<i=1kaxi
证毕。
所以说,碰到构造题的时候不要去想那么严格的解法,可以去大力猜一波结论,万一就对了呢?

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int N=25;int n,b[N];pair<int,int> a[N];int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&a[i].first),a[i].second=i;    sort(a+1,a+n+1);    int tmp=a[1].first;    for (int i=1;i<n;i++) a[i].first=a[i+1].first;    a[n].first=tmp;    for (int i=1;i<=n;i++) b[a[i].second]=a[i].first;    for (int i=1;i<=n;i++) printf("%d ",b[i]);    return 0;}
原创粉丝点击