#P11211. Interactive Random Number Generator Seed Recovery

    ID: 13279 Type: Default 1000ms 256MiB

Interactive Random Number Generator Seed Recovery

Interactive Random Number Generator Seed Recovery

This is an interactive problem.

Lloyd has a random number generator. For a given random seed \(s\) and generator type \(t\), the \(x\text{-th}\) (with \(x < p\)) random number produced is given by:

\[ r_{s,t}(x)=\begin{cases} s^x \bmod p &\quad t=1,\\[6pt] x^s \bmod p &\quad t=2,\end{cases} \]

where \(p\) is a fixed prime and \(0 \le s < p-1\). Before you start querying, the generator has already produced some random numbers; once you begin querying, no other random accesses occur (that is, the numbers you obtain form one continuous block). You can call the generator to get a random number. After several calls you must determine \(s\). It is guaranteed that a solution exists and that within 5 queries you can uniquely determine \(s\).


Implementation Details:

  • The problem is interactive.
  • The first line of input contains two positive integers \(t\) and \(p\).
  • You can perform the following two operations with the interactive library:
    • ?: Call the random number generator once. After that, you can read one integer from the standard input as the generated number.
    • ! s: Report the discovered seed \(s\) and then immediately terminate your program.
  • Remember to flush the output buffer after every operation.
  • The scoring is explained in the data section. It is guaranteed that if you use no more than 19930 queries (which is enough for at least 1 point), the interactive library will run in less than 100ms.

Note: For generator type \(t=1\), observe that if you make two consecutive queries, then if the responses are \(r_1\) and \(r_2\) corresponding to indices \(x\) and \(x+1\), we have \(r_2 \equiv s \cdot r_1 \; (\bmod\; p)\) (with the convention that if \(r_1=0\) then \(s=0\)). For generator type \(t=2\), you may need more queries; one correct strategy is to query 5 times to obtain responses \(r_1, r_2, r_3, r_4, r_5\). Suppose the first query corresponds to index \(k+1\) (with an unknown offset \(k\)). Then we have:

\[ \begin{aligned} r_1 &\equiv (k+1)^s \; (\bmod\; p),\\ r_2 &\equiv (k+2)^s \; (\bmod\; p),\\ r_3 &\equiv (k+3)^s \; (\bmod\; p),\\ r_4 &\equiv (k+4)^s \; (\bmod\; p),\\ r_5 &\equiv (k+5)^s \; (\bmod\; p). \end{aligned} \]

You can then brute force the unique \(s\) (and the corresponding residue \(a=k+1\) modulo \(p\)) over \(1 \le a < p\) and \(0 \le s < p-1\). It is guaranteed that in 5 queries you will have enough information to uniquely determine \(s\).

inputFormat

The first line contains two integers \(t\) and \(p\). After that, whenever you output a query (a line containing ?), you will receive an integer from the standard input which is the generator's response.

outputFormat

When you have determined the seed, output a line in the format ! s (without quotes) and terminate your program.

sample

1 17
15
11
! 3

</p>