Codeforces 121C-Lucky Permutation

問題概要

N個の数のK番目の順列のうち,以下の条件を両方満たす桁は何桁あるか
・前から見てlucky_numberな番号の桁である
・数値がlucky_numberである

解法

30!>>10^9なので
下30桁ぐらいについては愚直に調べる.
それ以外はluckynumberな桁全てが条件を満たす

実装(Ruby)

def is_lucky(s)
        while s>0
                return false if s%10!=7 && s%10!=4
                s/=10
        end
        return true
end
def fact(k)
        return 1 if k<=0
        return fact(k-1)*k
end
def lucky(now)
        res=[]
        return [] if now>1000000000
        return [now]+lucky(now*10+4)+lucky(now*10+7)
end
n,k=gets.split.map(&:to_i)
k-=1
remain=[]

def solve(n,remain,k)
        return [] if n==0
        n.times{|i|
                if k<fact(n-1)*(i+1) then
                        ans=[remain[i]]
                        remain.delete_at(i)
                        ans+=solve(n-1,remain,k-fact(n-1)*i)
                        return ans
                end
        }
end
if n<=30 then
        n.times{|i|
                remain.push(i+1)
        }
        if fact(n)<=k then
                puts -1
                exit
        end
        res=solve(n,remain,k)
        ans=0
        n.times{|i|
                ans+=1 if is_lucky(i+1) && is_lucky(res[i])
        }
        p ans
else
        (n-29).upto(n){|i|
                remain.push(i)
        }
        res=solve(30,remain,k)
        ans=0
        (n-29).upto(n){|i|
                ans+=1 if is_lucky(res[i-n+29]) && is_lucky(i)
        }
        lucky_number=lucky(0)
        lucky_number.shift
        lucky_number.each{|i|
                ans+=1 if i<n-29
        }
        p ans
end