今年是我第一次参加省级的比赛,发来的通知上说是ACM ICPC江苏省区比赛,但是去了那边变成了大学生程序设计大赛,去掉一个I的差别可很大。不过虽然不是International,不过难度也不少。今天就先分析其中一道题目:

题目是英文的,这里我就把翻译好的给大家,翻译不好还请见谅

给出一个正整数n(1<=n<=2001)。在n的左边可以放置另外一个数m,这样就组成一个新数mn,其中m必须小于等于n的一半。如果还有一个整数k<=m/2,那么还可以继续组成一个新数kmn....

比如有一个数12,你就可以在这个数左边放1~6,组成112,212.....612,接下来212又可以继续分成1212。

在举一个例子n=8

第一轮产生:18,28,38,48

第二轮18:不能产生新数

第三轮28:128

第四轮38:138

第五轮48:148,248

第六轮128、138、148:不能产生新数

第七轮248:1248

第八轮1248:不能产生新数


Input:

输入一个数n

Output:

一共产生了多少数

 Input:

8

Output:

10

这道题目这一看之下有点像一个多叉树,第一次我想了一下,发现可以用递归做。因为我们可以看到当n=8时有4个新数,n=4时有2个新数,n=2时有一个新数,n=1时没有新数。代码如下:

递归法

 

递归的潜在效率损失的确很大,测100前还没有什么性能差别,但是测到400,500的时候和动态规划的性能差别已经很大了(这个是事后的测试了)。当时比赛提交以后被判为“超时”,这个结果已经是我料到的。当时浙江师范和复旦大学的队伍给了我很大的压力。好不容易清醒下来,重新看了下题目。想到一道北大上做过的题目“Function Run Fun”,这道题目一开始也是用递归做,结果超时,最后是用动态规划做出来的。

        仔细研究题目时候,发现

当n=0时有0个新数,

当n=1时1个新数,

当n=2时2个新数,

当n=3时2个新数,

当n=4时4个新数,

当n=5时4个新数,

当n=6时6个新数

当n=7时6个新数,

当n=8时10个新数。

    打表之后发现

n8=n1+n2+n3+n4+1=1+2+2+4+1=10

n7=n1+n2+n3+1=1+2+2+1=6

....

n4=n1+n2+1=1+2+1=4

     得到这个结论之后就能打表做了,开辟一个2002大小的double数组,初始化好之后直接访问就可以了。代码如下

动态规划法

 

     利用打表的方法是空间换速度,直接寻址的速度还是非常可观的,最后这道题终于AC了。

 

Copyright © 2024 Samson小天
Powered by .NET 8.0 on Kubernetes