Permutation Power

Let σ \sigma be a permutation of { 1 , 2 , 3 , , 100 } \{1, 2, 3, \ldots, 100\} . Then there exists a smallest positive integer f ( σ ) f(\sigma) such that σ f ( σ ) = id \sigma^{f(\sigma)} = \text{id} , where id \text{id} is the identity permutation.

What is the largest value of f ( σ ) f(\sigma) over all σ ? \sigma?


Note: σ k \sigma^k is σ \sigma applied k k times in succession.


The answer is 232792560.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

2 solutions

Oliver Piattella
Sep 7, 2017

This is Landau's function g ( 100 ) g(100) . See e.g. here or here .

As already very well explained by Ivan, any permutation of n n objects can be decomposed in cycles. The sum of the lengths of the cycles must give n n and each cycle gives the identity if repeated as many times as its length. For example, consider the following permutation:

σ = ( 1 2 3 4 5 2 5 4 3 1 ) = ( 1 2 5 ) ( 3 4 ) \sigma = {{1\;2\;3\;4\;5}\choose{2\;5\;4\;3\;1}} = (1\;2\;5)(3\;4)

It is made up of a 3-cycle and a 2-cycle. The 3-cycle must be applied 3 times in order to give the identity whereas the 2-cycle has to be applied 2 times, as can be easily checked. Therefore, the full permutation σ \sigma must be applied 6 times, i.e. the LCM of 2 and 3, in order to give the identity.

Therefore, let's find a set of number which summed give 100 and whose LCM is the maximum possible. Using prime numbers is a good start, because their LCM is their product. Indeed, it can be shown that the product of the first m m primes (the primorial) is a lower bound of Landau's function (for a suitable m m ). Note that:

2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 = 100 2+3+5+7+11+13+17+19+23 = 100

And thus

LCM ( 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 ) = 2 3 5 7 11 13 17 19 23 = 223092870 \mbox{LCM}(2,3,5,7,11,13,17,19,23) = 2\cdot 3\cdot 5\cdot 7\cdot 11\cdot 13\cdot 17\cdot 19\cdot 23 = 223092870

This was my first guess, and it is wrong because it can be improved. Indeed, what counts in order to maximize the LCM is to have coprime numbers, not necessarily primes. We can improve the above result substituting 2 + 23 2 + 23 by 16 + 9 16 + 9 because in this case we have a factor 9 16 = 144 9\cdot 16 = 144 in the LCM rather than 2 3 23 = 138 2\cdot 3\cdot 23 = 138 . This gives:

LCM ( 3 , 5 , 7 , 9 , 11 , 13 , 16 , 17 , 19 ) = 5 7 9 11 13 16 17 19 = 232792560 \mbox{LCM}(3,5,7,9,11,13,16,17,19) = 5\cdot 7\cdot 9\cdot 11\cdot 13\cdot 16\cdot 17\cdot 19 = 232792560

which is the correct answer.

Ivan Koswara
Aug 22, 2017

Relevant wiki: Dynamic Programming

A permutation σ \sigma is a product of disjoint cycles. Suppose the cycles of σ \sigma have length a 1 , a 2 , a 3 , , a n a_1, a_2, a_3, \ldots, a_n . Then f ( σ ) = lcm { a 1 , a 2 , a 3 , , a n } f(\sigma) = \text{lcm} \{a_1, a_2, a_3, \ldots, a_n\} , because in order to set the i i -th cycle to be the identity, we need to raise σ \sigma to the a i a_i -th power. Thus our goal is to maximize lcm { a 1 , a 2 , a 3 , , a n } \text{lcm} \{a_1, a_2, a_3, \ldots, a_n\} , given the constraint that a 1 + a 2 + a 3 + + a n = 100 a_1+a_2+a_3+\ldots+a_n = 100 (because the cycles are disjoint).

Suppose a i = p q a_i = pq where p , q > 1 p, q > 1 are relatively prime (that is, a i a_i is not the power of a prime). Then p + q a i p+q \le a_i and lcm { p , q } = a i \text{lcm} \{p,q\} = a_i , so we may substitute the cycle with length a i a_i with several cycles: one of length p p , one of length q q , and remaining cycles of length 1 to make the number of elements equal. For example, if σ \sigma has a cycle of length 12, then we can split it off into a cycle of length 4, another cycle of length 3, and five cycles of length 1. This will give the same LCM, and hence same value of f f . Thus doing this will never make f f to decrease, and so we may assume that all a i a_i 's are powers of prime.

Now, if there are a i , a j a_i, a_j such that a i a j a_i | a_j and a i > 1 a_i > 1 , then we may replace the cycle with length a i a_i with a i a_i cycles of length 1, because the LCM is not changed ( lcm { a i , a j } = a j \text{lcm} \{a_i, a_j\} = a_j ). Thus we may also assume all a i a_i 's are relatively prime. Now, we have several powers of primes, all relatively prime, which add up to 100. The LCM is simply the product of all of them, so we need to maximize this product.

We can now use dynamic programming to solve this. Label the primes p 0 , p 1 , p 2 , p_0, p_1, p_2, \ldots in increasing order. We generalize the problem: let s o l v e ( s , k ) \mathtt{solve}(s,k) to be the maximum product of a 1 , a 2 , , a n a_1, a_2, \ldots, a_n , given that a 1 + a 2 + + a n = s a_1+a_2+\ldots+a_n = s , each a i a_i is the perfect power of a prime p p k p \ge p_k , and any two a i a_i 's are relatively prime. For example, s o l v e ( 5 , 0 ) = 6 \mathtt{solve}(5,0) = 6 , with a 1 = 2 , a 2 = 3 a_1 = 2, a_2 = 3 , but s o l v e ( 5 , 1 ) = 5 \mathtt{solve}(5,1) = 5 with a 1 = 5 a_1 = 5 , because we may not use p 0 = 2 p_0 = 2 . (And s o l v e ( 5 , 3 ) = 1 \mathtt{solve}(5,3) = 1 , since we may not use any of the primes 2, 3, 5, so we're stuck with setting a 1 = a 2 = = a 5 = 1 a_1 = a_2 = \ldots = a_5 = 1 .) Our goal is to compute s o l v e ( 100 , 0 ) \mathtt{solve}(100,0) .

The base case is if s < p k s < p_k . We cannot use any prime at all, so we can immediately conclude s o l v e ( s , k ) = 1 \mathtt{solve}(s,k) = 1 by setting all a i a_i to 1. We can now make use of recursion: in order to compute s o l v e ( s , k ) \mathtt{solve}(s,k) , we will take the maximum among the following:

  • Ignore p k p_k , so take the value of s o l v e ( s , k + 1 ) \mathtt{solve}(s,k+1) .
  • Let a 1 = p k e a_1 = p_k^e for some e e (and then all other a i a_i 's may not use p k p_k ), so take the value of p k e s o l v e ( s p k e , k + 1 ) p_k^e \cdot \mathtt{solve}(s - p_k^e, k+1) . We don't need to find the "right" value of e e ; simply iterate over all possible e e , as long as p k e s p_k^e \le s .

The correctness is easily seen, because this recursion is actually testing all possible combinations: either we ignore p k p_k , or one of the a i a_i 's is a power of p k p_k . This recursion will end, because each successive call increases k k and never increases s s ; thus at some point, we will compute s o l v e ( s , k ) \mathtt{solve}(s',k') where p k > s s p_{k'} > s \ge s' and thus we hit the base case. Finally, this will take at most O ( s 2 log s ) O \left( \frac{s^2}{\log s} \right) time: there are O ( s log s ) O \left( \frac{s}{\log s} \right) primes below s s , so there are that many values for k k , and there are O ( s ) O(s) values for s s . By memoizing computation, no call will be computed more than once.

The following is a Python 3 implementation of the above algorithm.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Primes up to 100, plus one more
primes = [ 2,  3,  5,  7, 11, 13, 17, 19, 23, 29,
          31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
          73, 79, 83, 89, 97, 101]

# Memoized computation
computed_solve = dict()

# solve function as defined
def solve(s,k):
    # If p_k > s, this is base case
    if primes[k] > s: return 1
    # If already computed, return it
    if (s,k) in computed_solve: return computed_solve[s,k]
    # Otherwise, this is a new call

    # Answer candidates
    candidates = []
    # 1. Ignore p_k
    candidates.append(solve(s, k+1))
    # 2. Take a_1 = p_k^e, try all possible e
    e = 1
    while primes[k]**e <= s:
        a1 = primes[k]**e
        candidates.append(a1 * solve(s-a1, k+1))
        e += 1

    # Find maximum among all candidates
    answer = max(candidates)
    # Add to memoized computation and return
    computed_solve[s,k] = answer
    return answer

# Actual problem
solve(100, 0)
# Returns 232792560

Alternatively, we can look up the value of Landau's function g ( 100 ) g(100) , which is exactly what we want...

Mark Hennings - 3 years, 9 months ago

Log in to reply

I didn't know it has a name. But this gives a way to compute the values of Landau's function. Not necessarily the fastest, but it's pretty reasonable.

Ivan Koswara - 3 years, 9 months ago

Log in to reply

Here is my Delphi code - very quick. (Delphi does not have an in-built integer power function with native integer output, so I rolled my own)

procedure TForm1.Button5Click(Sender: TObject);
const
primes: array[1..25] of Integer = (2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 
41, 43, 47, 53, 59, 61,   67,71, 73, 79, 83, 89, 97);

function GetM(a,b: Integer): LongInt;  
var
u: Integer; 
begin
  if b = 1 then
   begin
   Result := 1;
   while primes[1] * Result <= a do Result := Result * primes[1];
   end
  else
   if a = 0 then
    Result := 1
   else
     begin
     Result := GetM(a,b-1); 
     u := 1;
     while primes[b]*u <= a do
       begin 
         u := primes[b]*u;
         Result := Max(Result,u*GetM(a-u,b-1));
      end;
    end;
end;

begin
Label1.Caption := IntToStr(GetM(100,25));
end;

Mark Hennings - 3 years, 9 months ago

Log in to reply

@Mark Hennings Yes, that's the same algorithm as mine.

Ivan Koswara - 3 years, 9 months ago

Log in to reply

@Ivan Koswara You seem to be using memory to avoid repeat calls. My recursive routine GetM(a,b) only calls GetM(c,d) for values c,d with c + d < a + b c+d<a+b , so there cannot be any repeat.

Mark Hennings - 3 years, 9 months ago

Log in to reply

@Mark Hennings There can still be some repeat; for example, when you compute G e t M ( 5 , 3 ) \mathtt{GetM}(5, 3) , one path goes G e t M ( 5 , 3 ) G e t M ( 5 , 2 ) G e t M ( 2 , 1 ) G e t M ( 0 , 0 ) \mathtt{GetM}(5, 3) \to \mathtt{GetM}(5, 2) \to \mathtt{GetM}(2, 1) \to \mathtt{GetM}(0, 0) (taking no 5, one 3, and one 2), while another goes G e t M ( 5 , 3 ) G e t M ( 0 , 2 ) G e t M ( 0 , 1 ) G e t M ( 0 , 0 ) \mathtt{GetM}(5, 3) \to \mathtt{GetM}(0, 2) \to \mathtt{GetM}(0, 1) \to \mathtt{GetM}(0, 0) (taking one 5, no 3, and no 2).

...okay, that explicit example might be wrong because you immediately cut down computation when a = 0 a = 0 or b = 1 b = 1 , but it's definitely possible to generalize it; say, G e t M ( 22 , 5 ) \mathtt{GetM}(22, 5) will compute G e t M ( 2 , 1 ) \mathtt{GetM}(2, 1) twice.

Ivan Koswara - 3 years, 9 months ago

Log in to reply

@Ivan Koswara Agreed, since 7 + 11 = 5 + 13 7+11=5+13 , GetM(26,6) will call GetM(8,2) more than once.

However, since my routine takes less than a millisecond to run, with no change to GetTickCount, I am not too worried about performance.

Mark Hennings - 3 years, 9 months ago

Log in to reply

@Mark Hennings Yes, when I wrote my first program to solve this, I didn't use memoization and it went fast enough as well. (Actually, it was about 0.5 seconds on Python; I'm not sure why it was pretty slow, but for the purpose of the problem that's fast enough.) It's only when I wrote the solution that I found using memoization simplified the time complexity analysis.

Ivan Koswara - 3 years, 9 months ago

Log in to reply

@Ivan Koswara Python vs. Delphi: Sounds like the difference between interpreted code and compiled code.

I suspect that maintaining the memory list - particularly searching for entries - will have a performance impact after eventually.

Mark Hennings - 3 years, 9 months ago

Log in to reply

@Mark Hennings It's possible that part of it is because of Python being interpreted, but I have my rule of thumb that approximately 1 0 6 10^6 operations can be done in one second on my computer ( 1 0 7 10^7 on online judges like Codeforces and such, because my computer is slow and online judges are fast), and the analysis above says that it takes only about 2500 × constant 2500 \times \text{constant} operations. I believe the constant here is small (around 10), so it doesn't explain needing 0.5 seconds.

The memory list is a dictionary, and so is a hash table. Assuming no collisions, lookups should be constant time.

Ivan Koswara - 3 years, 9 months ago

Huh. The primes from 2 to 23 conveniently sum to 100. Why isn't their product the maximum we can achieve?

Bryan Hung - 3 years, 9 months ago

Log in to reply

Because cycles of length 2 , 3 , 23 2, 3, 23 reach the identity permutation faster than cycles of length 16 , 9 , 1 , 1 , 1 16, 9, 1, 1, 1 . We can replace 2 , 3 , 23 2, 3, 23 with 16 , 9 , 1 , 1 , 1 16, 9, 1, 1, 1 to obtain a higher f f .

Ivan Koswara - 3 years, 9 months ago

The last part can actually be done by hand or with just a single loop. The idea is to iterate up from 1. Every time you see a prime or a power of a prime you add it into the list, if the list already contains a lower power of that prime you remove it. Iteration continues until the sum of the list elements is less than 100 (or any K you want to calculate it for), the number causing an overflow is not included. So it is like: {2} -> sum=2 {2,3} -> s=5 {3,4} -> s=7 {3,4,5} -> s=12 ... {5,7,9,11,13,16,17,19} -> s=97 {5,7,9,11,13,16,17,19,23} -> s=120

Aliaksei Memelau - 3 years, 8 months ago

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...