[Code jam 2010]Qualification Round题目分析

Code Jam 2010:http://code.google.com/codejam

 

Snapper Chain

 

其实这是一道英语阅读理解题,真的。只要读懂了就能轻松的做出来。

 

Snapper是一种带电子开关的插线板(我的理解)。它的一边是插头另一边是插孔。电子开关有两种状态:开和关,只有当插头通电是开关才能切换状态,且插头断电后开关状态保持不变。现在有N个snapper连接成一条链,链的一段连接在电源上,另端连接一个台灯。所有snapper的初始状态都是关。每次操作会触发所有snapper的开关,问这样执行K次操作后,台灯是不是亮的。

 

OK,我们可以用0和1来表示snapper的两种状态。这样就可以将snapper chain表示成为一个N bits的数,如下:

台灯-00000000-电源

每次操作时,第 i 位snapper的状态只有满足 右边是电源或者右边全是1 才会变化。

这样就可以列出一个操作次数和snapper的对应表:

K      Snappers

1      00000001

2      00000010

3      00000011

4      00000100

 

这样,规律就一目了然了。所以只有当K的最低N位全是1,台灯才会亮。

读懂了题目就只需要一行代码就能够算出来了。

 

Fair Warning

 

这是这一轮里最困难的一道题了。

给定N个正整数t1,t2...tn, 求一个y的最小值,使得所有 ti + y 都有一个共同的最大公因数T,且T的值最大。

 

设有两个正整数a,b 且 a > b 。 a + y 和 b + y的最大公因数是T。则可以表示为

a + y = pT

b + y = qT

p,q为整数且 p > q

 

所以 (a + y) - (b + y) = (p-q)T = a - b ,换而言之呢,a-b 和 a + y 和 b+y 的最大公因数都是T。

a + y的值虽然不知道, 但是 a-b 却是已知的。

将给出的N个数字两两相减, 所有的差的最大公因数就是T。而知道T以后呢,y就可以很轻松的算出了。

 

具体的代码如下(由google给出,比我的算法简单很多):

 

 

说句题外话,google果然还是偏向pythoner的,这道题要处理1050的数字,这对python来说无所谓,但是对于其他的语言就需要专门的大数库了。

 

Theme Park

 

这道题目的large input拥有所有题目里的最低正确率40%,算法的时间复杂度不好就肯定在8分钟内计算完。

 

游乐场的过山车的容量是K,每天运行R次,有N组人排队,每组的人数是gn ,组不能拆分,当过山车容不下下一组的时候就开始运行。坐完的人会按照开始的顺序重新排到队尾(真是好顾客)。每人每次1欧元,问一天能收入多少钱?

 

很简单的题目对吧,

 

这的算法的复杂度是O(NR), 解决small input肯定没问题,但是large input里:

1 ≤ R ≤ 108

1 ≤ N ≤ 1000

在规定的时间里决定算不完(你要是有一台深蓝那样的电脑请当我没说)。

 

观察算法可以发现每次从位置i开始进人,一定会到位置j结束。我们可以把这个提前算出了,新算法如下:

 

这样算法的复杂度变成了O(N),在large input的时候比上一个算法提高了1000倍。但是这个还不够好。

事实上我用的就是这个算法,在最后30内才算完(幸好超频了CPU)。

 

通过分析题目, 可以发现在R > N的时候存在必定存在一个循环,即从一个位置i开始,经过x轮后,又从i开始。

这样R次循环就可以分成3部分:

1 经过m轮后,到达位置i

2 经过x轮,有回到i, 循环n次

3 不够一个循环的p轮

 

m和p的值都很小,很容易求得1和3阶段的收入 u,w

2阶段的收入就是 n * v 其中v是每个循环的总收入

 

具体代码如下:

 

 

总结:

Code jam 的small input和large input, 分别考察的是算法的正确性和算法的效率。一般而言会有多种方法解出small input, 但是对于large input,高效的算法一般都能够在很短的时间内完成。而没有优化的算法基本都会超时。所有,确保算法正确性的同时必须考虑算法的效率。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值