google code jam exercise——Your Rank Is Pure

继续Round 1B 2010。第二道题没理解题目,第三道题题目可以理解,但是算法又折腾了好久。还是先看第三道题吧。

给定一个集合S={2,3,...n},它的子集S' 满足性质:n在S'中是第k个元素,那么k应该也在S'中,同样地,k是第k'个元素,那么k'应该也在S'中,经过有限步,k=1,不在S'中,称n对于S'是Pure Rank。那么给定一个n,求S'的个数。

在Content Analysis中,给除了动态规划算法的算法。我怎么觉得好多题都是动态规划,我正好不太懂态规划。看看具体算法如下,

如果n是一个集合S'的pure rank,S''=S' ^ {1,2,...k},那么k就是S''的pure rank。动态规划算法就是要找出从S''到S'的方法。

S'有k个元素,S''有k'个元素,那么从S'到S'',需要从{k+1,k+2,...n-1}中选k-k'个元素。

用count[n][k]表示有k个元素的,n为pure rank的集合S'的个数,那么就有count[n][k] = sum count[k][k']*C[n-k-1][k-k'-1] for k'=1...k-1

由于最后的数可能会比较大,在累加的过程中需要对100003取余。取余不能用一次大于等于100003就减掉的方法替代。

最后代码如下:

#!/usr/bin/python
#encoding:UTF-8
#Filename:FileFixIt.py

import sys

def solveN(n):
    comb = [[0 for j in xrange(n+1)] for i in xrange(n+1)]
    j = 0
    for i in xrange(n+1):
        comb[i][j] = 1
        comb[i][i] = 1
    for i in xrange(1,n+1):
        for j in xrange(1,i):
            comb[i][j] = comb[i-1][j]+comb[i-1][j-1]
            if comb[i][j]>=100003:
                comb[i][j] = comb[i][j]%100003

    count = [[0 for j in xrange(n+1)] for i in xrange(n+1)]
    for i in xrange(2,n+1):
        count[i][1] = 1
    for i in xrange(3,n+1):
        for j in xrange(2,i):
            count[i][j] = 0
            for k in xrange(1,j):
                count[i][j] += count[j][k]* comb[i-j-1][j-k-1] 
                if count[i][j]>=100003:
                    count[i][j] = count[i][j]%100003
#    print "count:"            
#    for i in xrange(2,n+1):
#        for j in xrange(1,i):
#            print "count[%d][%d] %d" %(i,j,count[i][j])
#    cnt = 0
#    for j in xrange(1,n):
#        cnt += count[n][j]
#    print "cnt:",cnt
#    return cnt
    return count
    

inname = "input.txt"
outname = "output.txt"
if len(sys.argv)>1:
    inname = sys.argv[1]
    outname = inname.rstrip(".in")
    outname = outname + ".out"
fin = open(inname,"r")
fout = open(outname,"w")

testCaseNum = int(fin.readline().rstrip("\n"))
caseNum = 0

lines = fin.readlines()
allCase = [int(line.rstrip("\n")) for line in lines]
maxN = max(allCase)
count = solveN(maxN)

for caseNum,n in enumerate(allCase):
    cnt = 0
    for j in xrange(1,n):
        cnt += count[n][j]
        if cnt>=100003:
            cnt = cnt%100003
    answer = "Case #%d: %d\n" %(caseNum+1,cnt)
    fout.write(answer)

fin.close()
fout.close()

最后small和large case测试都通过了,large case需要比较长的时间。

有个问题,有重复的吗?

 

原文地址:https://www.cnblogs.com/Frandy/p/google_code_jam_pure_rank_python.html