SRM练习题550Point解析之一:Lottery彩票
本文是解析Top Coder的SRM练习题550Point系列的第一篇,Lottery彩票。
问题描述是全英文的,由于英文水平有限,所以发了不少时间才完全看明白。本人觉得Top Coder的题目挺有趣的,激发着我的智慧去解决它。在这个过程中,自己解决实际问题的能力得到了提升,而且算法能力、编程基础也得到了巩固、加强。在此与大家一起分享,一起成长。
TopCoder竞赛介绍http://www.wyu.cc/viewthread.php?tid=53252
由于未授权,问题描述不能在此贴出,十分遗憾!获得原题请登录TopCoder: Practice Room —1 SRMs—1-16—1 SRM 144 DIV1
一、 转化为数学模型
首先,从最简单的情况入手,第一种规则[10,2,F,F]表示此类彩票由任意两个1-10的数字组成,不需要按升序排序(任意序列),也可以出现相同的数字,如{1,2},{10,5},{4,4}都是有效的彩票。这是最简单的一种情况,按照排列的数学知识可以知道,这种规则彩票的有效个数是10*10=100个。更一般的规则为[max,count,F,F],有效个数为max的count次幂个,即max count。代码实现如下:
1Int64 result=(Int64)Math.Pow(max, count);//数据很大,有可能超过32位
第二种规则[10,2,F,T]表示此类彩票由任意两个1-10的数字组成,数字系列任意排序,但是不能出现重复的。如{3,3}是无效的彩票,按照排列的知识可以知道,此类彩票的个数是10*9=90个。更一般的规则为[max,count,F,F],有效个数为max*(max-1)*…*(max-count+1)个。代码实现如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
第三种规则[10,2,T,F]表示此类彩票由任意两个1-10的数字组成,但是数字系列必须是按升序排序,可以重复出现。我们可以知道当第一个数字为1时,第二个数字可以是1-10,这10个数字;当第一个数字为2时,第二个数字可以是2-10,这9个数字,由此可以推出,当第一个数字为10时,第二个数字只可以为10,这1个数字。那么所有的符合规则有效的彩票个数为10+9+8+7+6+5+4+3+2+1个。
如果可以输入的数字为3个,即[10,3,T,F]时,同样的,当第一个数字为1时,后面的两个数字同[10,2,T,F]一样,有10+9+…+1种情形;当第1个数字为2时,后面的两个数字有9+8+…+1种情形。整个数学模型如下:
2个数字: 10+ 9 + 8 + 7 +6 + 5 +4 + 3 + 2 + 1
3个数字:(10+9+…+1)+(9+8+…+1)+(7+6+…+1)+…+(2+1)+1
4个数字:((10+9+…1)+(9+8+…+1)+…+1)+((9+8+…+1)+…+1)+…+1
… … …
一般的[max,count,T,F]时为,领头的最大数字为max。
可以看出每种情况都是由10个单元相加组成的和,而且当数字增加一个的时候,每个单元的值都是前一种情况下,它本身及其后面所有单元的和,这就是一种典型的迭代,代码实现如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
第四种规则[10,2,T,T]表示此类彩票由任意两个1-10的数字组成,但是数字系列必须是按升序排序,而且不可以重复出现。我们可以知道当第一个数字为1时,第二个数字必须是2-10,这9个数字;当第一个数字为2时,第二个数字必须是3-10,这8个数字。同理可知符合规则有效的彩票个数为
9+8+7+6+5+4+3+2+1个。
如果可以输入的数字为3个,即[10,3,T,T]时,同样的有效的个数为
(8+7+6+5+4+3+2+1)+(7+6+5+4+3+2+1)+…+1
一般的[max,count,T,T]时为领头的最大数字为max-count+1。代码实现同第三种规则。
二、 多关键字排序
实现多关键字排序,有两种方法:第一种是,先对最主要的关键字排序,再对有相同最主要关键字值的子序列进行次关键字排序,依此类推,此方法称为Most Significant Digit First (MSD)法;第二种是,先对最次要的关键字进行全体排序,再对次要的关键字进行全体排序,依此类推,此方法称为最Least Significant Digit First (LSD)法。
MSD法和LSD法只是约定了“关键字的次序”来排序,但并未约定对每一个关键字使用的排序方法(如快速排序,插入排序等)。MSD与LSD法的实现区别是:MSD法根据关键字次序对序列逐层进行分割成若干个子序列,再对子序列进行排序;LSD法不必分割成子序列,对每个关键字都是整个序列参加排序,但必须是稳定排序。
MSD的代码实现方法:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
三、 常用的FCL框架类库
String类的Split方法
返回由指定的字符或字符串数组分割此String实例而得到的子字符串数组。
Array类的Sort方法
此方法使用QuickSort快速排序算法,是不稳定排序算法。
条件运算符xxx?xxx:xxx
四、 完整代码(略)
感觉整个贴出来太啰嗦了,o(∩_∩)o...