Jump to content

Yet another algorithmic problem

Nineshadow

A safe has a very special kind of "lock". It displays a "public key", made out of two parts : a vector of integers v={v0,v1,...,v9} and an integer k. To gain access to the safe, you must calculate the k-th integer (in ascending order) which can be formed with v0 digits of 0, v1 digits of 1, v2 digits of 2 and so on, modulo 109+7.

Examples :

v={1,1,0,0,0,0,0,0,0,0}:
	for k=1, the answer is 1
	for k=2, the answer is 10

v={1,1,1,0,0,0,0,0,0,0}:
	for k=1, the answer is 12
	for k=2, the answer is 21
	for k=5, the answer is 201

v={1,2,0,0,0,0,0,0,0,0}:
	for k=2, the answer is 101

Note that the number you are asked for can start with 0. If it starts with 0-s, the 0-s simply get discarded, meaning that 012=12, and 000012=12.

Restrictions

  • you are given <=5.000 queries.
  • the number you need to form will have at most 70.000 digits (v0+v1+v2+...+v9<=70.000)
  • k <= 1012
  • a solution is guaranteed
  • time : 2sec
  • memory : 65536 kbytes

___________________________________________________________________________________________________

 

I think it is clear that the problem asks what's the k-th lexicographic permutation of a certain set.

For example, if v={1,1,1,0,0,0,0,0,0,0}, then the first permutation will look like this : {0,1,2}. If v={1,2,0,0,0,0,0,0,0,0}, the first permutation will look like this : {0,1,1}.

It should also be noted that k is pretty small compared to the number, considering the amount of digits it can have.

However, the interesting part comes when we take into consideration the modulo. Calculating the modulo for a number with 70.000 digits is not at all convenient. So there's definitely something else in play here.

@fizzlesticks

i5 4670k @ 4.2GHz (Coolermaster Hyper 212 Evo); ASrock Z87 EXTREME4; 8GB Kingston HyperX Beast DDR3 RAM @ 2133MHz; Asus DirectCU GTX 560; Super Flower Golden King 550 Platinum PSU;1TB Seagate Barracuda;Corsair 200r case. 

Link to comment
Share on other sites

Link to post
Share on other sites

I haven't done the math on it but it seems to me that if you place all digits in ascending order, then scale the most significant figure to the right k-1 times, you'll find the solution (ignoring the modulo). This seems pretty efficient to me.

 

I'm confused when it comes to the modulo, 109+7 is a prime number...  NVM, I'll have to think about it

 

By the way, what sort of safe gives you a hint on how to open it? :P

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Sauron said:

By the way, what sort of safe gives you a hint on how to open it? :P

The one that gives you problems to solve I guess.

Finding just the k-th permutation isn't that hard. You can do it pretty easily with the factorial number system, at least theoretically. But additionally, you need to find the number made from that permutation, modulo 109+7. Yes, 109+7 is a prime number, which will make calculations easier if modular arithmetic arises later on. But so far...eh? I don't have too many useful ideas.

I thought about writing the permutation as a number in base 109+7. That should be pretty cool. In that situation, the modulo will be just the least significant digit of the permutation. However, the issue is actually calculating the permutation in base 109+7, without having to do it in base 10 and then converting it.

i5 4670k @ 4.2GHz (Coolermaster Hyper 212 Evo); ASrock Z87 EXTREME4; 8GB Kingston HyperX Beast DDR3 RAM @ 2133MHz; Asus DirectCU GTX 560; Super Flower Golden King 550 Platinum PSU;1TB Seagate Barracuda;Corsair 200r case. 

Link to comment
Share on other sites

Link to post
Share on other sites

@Sauron

More specifically, to generate the k-th permutation given the frequency of digits:

Consider the number x with n digits, d0,d1,...,dn-1.

Order the digits such that d1<=d2<=...<=dn.

Let the frequencies with which the digits appear in the number x be f0,f1,...,f9.

Then the number of distinct permutations of the digits of x will be nr=n!/(f0!*f1!*...*f9!). We are basically eliminating all the permutations in which only identical digits are permuted.

We don't need to generate all the permutations to reach the k-th permutation. So we do this:

1.Calculate the number of distinct permutations which begin with the smallest digit d0:

p=(n-1)!/((f0-1)!*f1!*...*f9!)=nr*f0/n

2.If p>n, then the permutation we're looking for begins with the digit d0. We continue searching for the second digit, eliminating the digit d0 from x, equivalent to decrementing f0, in a recursive manner.

3.If p<n, then the permutation begins with a larger digit, and we go back to step 1, while keeping our results included into p.

4.If p=n, then we've used all the digits of x, and we've calculated the permutation.

You can also think about it using the factorial number system.

 

This works fine, except it's not fast enough for this problem. Or at least the  next step isn't, the step in which you turn the permutation into the required number.

 

i5 4670k @ 4.2GHz (Coolermaster Hyper 212 Evo); ASrock Z87 EXTREME4; 8GB Kingston HyperX Beast DDR3 RAM @ 2133MHz; Asus DirectCU GTX 560; Super Flower Golden King 550 Platinum PSU;1TB Seagate Barracuda;Corsair 200r case. 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×