您的位置:首页 > 其它

Ural 1082|Gaby Ivanushka|数学推导|快速排序|程序分析

2017-10-06 22:47 218 查看
http://acm.timus.ru/problem.aspx?space=1&num=1082

题目大意

给定以下程序

#include <stdio.h>
long c;
long A
;

long P(long l, long r)
{
long x=A[l],
i=l-1,
j=r+1,
t;
while(1)
{
do{--j; ++c;}
while(A[j]>x);
do{++i; ++c;}
while(A[i]<x);
if(i<j)
{
t=A[i];
A[i]=A[j];
A[j]=t;
}
else return j;
}
}

void Q(long l, long r)
{
long n;
if(l<r)
{
n=P(l,r);
Q(l,n);
Q(n+1,r);
}
}

int main(void)
{
c=0;
for(long i=0; i<N; ++i)
scanf("%ld", &A[i]);
Q(0,N-1);
if(c==(N*N+3*N-4)/2)
printf
("Beutiful Vasilisa");
else printf
("Immortal Koshcei");
return 0;
}


请你构造一个数列使得程序输出
Beautiful Vasilisa


输入

一行一个整数n表示数列长度。

输出

输出n个整数表示你构造的数列,要求是程序能够输出
Beautiful Vasilisa


样例输入

3


样例输出

3 7 19


题解

发现这个程序就是快速排序给定的数列,然后统计i和j指针的移动次数和c。我们的任务就是构造一个序列使其

c=n2+3n−42

由于给定的程序是快速排序,因此我们只关心数列元素之间的大小关系。观察样例输出发现数列是单调增的。因此我们假设严格单调增的数列满足题意。我们构造这样的一个数列,那么执行
P
时,我们取的x为数列片段中的最小值,那么i就从L−1走到L,j从R+1走到L,总共移动了R−L+2次。每次Q(L,R)调用完P(L,R)后,会接着调用Q(L,L)和Q(L+1,R),又Q(L,L)=0,所以Q(0,n−1)相当于

c=∑0≤i<n−1P(i,n−1)=∑0≤i<n−1(n−1)−i+2=(n−1)(n+1)−[0+1+⋯+(n−2)]=n2−1−[1+(n−2)](n−2)2=n2+3n−42

所以我们构造一个严格单调递增的数列即可

#include <cstdio>

int main() {
int n, i;
scanf("%d", &n);
for (i = 0; i < n; ++i) printf("%d ", i);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: