B3: The Hidden Polynomial II

Time Limit: 3 seconds

Memory Limit: 512 MiB

Score: 600 points

Problem Statement

Story

We are the QCoder Order, worshippers of quantum programming. We have a hidden polynomial, f(x)f(x), that has been protected for centuries. It is defined using an nn-bit odd integer AA and an nn-bit integer BB as follows:

f(x)=Ax2+Ax+Bf(x) = Ax^2 + Ax + B

Recently, we performed a sacred ritual to transfer this polynomial to an oracle OO. If the ritual was successful, the oracle OO should behave as follows:

xyOxy(f(x)mod2n)\ket{x}\ket{y} \xrightarrow{O} \ket{x}\ket{y \oplus (f(x)\bmod 2^n)}

Here, \oplus denotes the bitwise XOR operator, and (f(x)mod2n)(f(x)\bmod 2^n) denotes the remainder when f(x)f(x) is divided by 2n2^n.

Unfortunately, because the ritual's procedure is extremely complicated, no one knows if the oracle was generated correctly. We know that if the ritual failed, the oracle OO would acquire an extra phase and behave as follows:

xyO(1)f(x)/2nxy(f(x)mod2n)\ket{x}\ket{y} \xrightarrow{O} (-1)^{\left\lfloor f(x) / 2^n \right\rfloor}\ket{x}\ket{y \oplus (f(x)\bmod 2^n)}

Here, f(x)/2n\left\lfloor f(x) / 2^n \right\rfloor denotes the quotient when f(x)f(x) is divided by 2n2^n.

Your mission is to determine whether the ritual succeeded—i.e., whether the oracle OO has been implemented correctly.

Note that the polynomial f(x)f(x) is our top secret. To protect the details of f(x)f(x), you can only call the oracle once.

Detailed Description

Given an integer nn, you may implement any operations you like on a 2n2n-qubit quantum circuit qcbefore\mathrm{qc}_{\mathrm{before}}, and on a quantum circuit qcafter\mathrm{qc}_{\mathrm{after}} that has 2n2n qubits and one classical register.

Implement operations on these quantum circuits that satisfy the following requirement.

The candidate oracles O1O_1 and O0O_0 act on basis states xy\ket{x}\ket{y}, where 0x<2n0 \leq x < 2^n and 0y<2n0 \leq y < 2^n, as follows:

xyO1xy(f(x)mod2n)\ket{x}\ket{y} \xrightarrow{O_1} \ket{x}\ket{y \oplus (f(x)\bmod 2^n)} xyO0(1)f(x)/2nxy(f(x)mod2n)\ket{x}\ket{y} \xrightarrow{O_0} (-1)^{\left\lfloor f(x) / 2^n \right\rfloor}\ket{x}\ket{y \oplus (f(x)\bmod 2^n)}

When qcbefore,O,qcafter\mathrm{qc}_{\mathrm{before}},\,O,\,\mathrm{qc}_{\mathrm{after}} are applied in this order to the zero state 0\ket{0}, the measurement result written to the classical register must be 11 if O=O1O=O_1, and 00 if O=O0O=O_0.

Constraints

  • n>2n > 2
  • 0A,B<2n0 \leq A, B < 2^n
  • AA is odd.
  • Integers must be encoded by little-endian.
  • Global phase is ignored in judge.
  • The submitted code must follow the specified format:
    • before_oracle(n: int) -> QuantumCircuit: the quantum circuit qcbefore\mathrm{qc}_{\mathrm{before}} before calling the oracle.
    • after_oracle(n: int) -> QuantumCircuit: the quantum circuit qcafter\mathrm{qc}_{\mathrm{after}} after calling the oracle. You must write the measurement result to the classical register c in this circuit.
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
 
"""
You can apply measurement as follows
         (e.g., when measuring x[0]):
qc.measure(x[0], c[0])
"""
 
 
def before_oracle(n: int) -> QuantumCircuit:
    x = QuantumRegister(n)
    y = QuantumRegister(n)
    qc = QuantumCircuit(x, y)
 
    # Write your code here:
 
    return qc
 
 
def after_oracle(n: int) -> QuantumCircuit:
    x = QuantumRegister(n)
    y = QuantumRegister(n)
    c = ClassicalRegister(1)
    qc = QuantumCircuit(x, y, c)
 
    # Write your code here:
 
    return qc

In the judge, the functions are called in the following order:

  1. before_oracle(n)
  2. (the oracle OO)
  3. after_oracle(n)

After that, the judge concludes that “the ritual succeeded” if c=1c = 1, and that “the ritual failed” if c=0c = 0.

Hints

Open
  • You can use the following code to test your solution in your local environment.
    • Note that you need to define before_oracle, oracle, and after_oracle in advance.
from qiskit_aer import AerSimulator
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister, transpile
 
# Define or import before_oracle / oracle / after_oracle here.
 
# Example input
n: int = 3
A: int = 1  # A is odd
B: int = 4
 
# Build the circuit
x = QuantumRegister(n)
y = QuantumRegister(n)
c = ClassicalRegister(1)
main_qc = QuantumCircuit(x, y, c)
main_qc.compose(before_oracle(n), inplace=True)
main_qc.compose(oracle(), inplace=True)
main_qc.compose(after_oracle(n), inplace=True)
 
# Simulate the circuit and retrieve the contents of register c
simulator = AerSimulator()
job = simulator.run(
    transpile(main_qc, simulator),
    shots=1024,
)
counts: dict[str, int] = job.result().get_counts()
print(f"Measurement statistics: {counts}")

Please sign in to submit your answer.