UVa 11384 Help is needed for Dexter (构造解并证明)

来源:互联网 发布:windows 日志备份 编辑:程序博客网 时间:2024/05/16 13:00

-
来源:《算法竞赛入门经典训练指南》第1章例题10、UVa-11384
题目描述:
对于序列{1...n},求最小的操作数使得每个数都变成零。这里的合法操作指的是从原序列中指定任意多个数,减去同一个正整数。
题目分析:

如果只要AC,什么都不用说直接蒙log2n+1就对了,能找到的Solution除了小白菜又菜(版刷UVa的著名博主)尝试给出了证明,此外就都是小学生找规律就做出来了。目标是AC,这一点问题也没有,够快、够准。


这里给出严谨的证明。 对于数值上相同的数,视作同一个,或者说只记一次。首先对于m>n,必然有f(m)f(n)。这是因为可以将A={1..n}视为B={1..m}的子集,任意零化B的操作序列必然同时零化A,只需对相同的数进行相同的操作,A中不存在的数的操作不做即可。


- - - - 更新:嘛我发现好像可以证得更简略一点,对于下面提到的g,既然已经证出了对于题目序列有f(a)=g(a)+1=m+1,那就证完了嘛。- - -


于是有f(2k)f(k),接下来我们证明f(2k)f(k)。设k[2m,2m+1),则2k[2m+1,2m+2)。考虑对2a个两两不等的正数进行一次合法操作,若选择了至少a+1个,由于减数相同,操作后有不少于a个各不相同的正数;若选了不超过a个,则没有选上的数至少a个,同样有操作后至少a个正数数各不相同(这个结论对于2a+1时也成立,证明类似)。进一步的,定义g(a)为最小的操作数,使得a个不同的正数转换成1个不同的正数,则按照上边的讨论有,对于a=2m+l(0l<2m)g(a)=m,实际上对于一般的a个不同的数,这里只能得到,但按照那个猜出来的办法,我们确实地构造出了一个方案使得对于题目所给的特定序列,等号可以取到。考虑符合题意的零化操作序列,其最后一步必然是对某一个(实际上可能是一组相同的)数同时减去这个数本身得到0,因而有f(k)=g(k)+1f(2k)=g(2k)+1,根据上面对k范围的界定,结合g的表达式就有f(k)f(2k),于是f(2k)>f(k),由于f(2k)是正整数,而我们又构造出了使得f(2k)=f(k)+1的方案,这样就证明了构造的解确实是最优的。


猛然发现好像构造方法没说,这个其他题解随便搜一下吧。简单地说,从中间二分,再注意红色字体说的,也很好猜。

//  Created by wander on 16/06/21.//  Copyright © 2016年 W4anD0eR96. All rights reserved.//  From: UVa-11384//  Sort: 贪心算法-构造#include "bits/stdc++.h"using namespace std;int n;int main() {#ifdef DEBUG  freopen("in", "r", stdin);  freopen("out", "w", stdout);#endif  while (~scanf("%d", &n))    printf("%d\n", (int)log2(n) + 1);  return 0;}
0 0
原创粉丝点击