告诉你
每次你可以向交互库询问 ? x y(
我们先考虑
这种情况下,询问次数是
这样我们就解决了
然后我们考虑怎么找素数,我们考虑随机找一些位置并尝试将其确定下来。我们先大概看看应该需要找多少个位置,我们考虑由于素数密度越来越疏,我们就当是最大值是
由于附赠了
由于交互题写了很多调试语句所以代码可能有点小长 qaq
typedef long long LL;
int n;
LL ask(int x, int y) {
assert(1 <= x && x <= n && 1 <= y && y <= n);
std::cout << "? " << x << ' ' << y << std::endl;
std::cout.flush();
LL ans;
std::cin >> ans;
return ans;
}
namespace solve_small {
const int maxn = 105;
LL lcm[maxn][maxn];
void solve() {
memset(lcm, 0, sizeof(lcm));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
lcm[i][j] = lcm[j][i] = ask(i, j);
}
}
std::pair<int, int> idans(0, 0);
if (n == 3) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
if (lcm[i][j] > lcm[idans.first][idans.second]) {
idans = std::make_pair(i, j);
}
}
}
std::vector<int> ANS(4);
ANS[idans.first] = sqrt(lcm[idans.first][idans.second]);
ANS[idans.second] = ANS[idans.first] + 1;
ANS[6 - idans.first - idans.second] = ANS[idans.first] - 1;
if ((LL) ANS[idans.first] * ANS[6 - idans.first - idans.second]
/ std::__gcd(ANS[idans.first], ANS[6 - idans.first - idans.second])
!= lcm[idans.first][6 - idans.first - idans.second]) {
std::swap(ANS[idans.first], ANS[idans.second]);
}
std::cout << "! ";
for (int i = 1; i <= 3; ++i) {
std::cout << ANS[i] << ' ';
}
std::cout << std::endl;
std::cout.flush();
} else {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
lcm[i][i] = std::__gcd(lcm[i][i], lcm[i][j]);
}
}
std::cout << "! ";
for (int i = 1; i <= n; ++i) {
std::cout << lcm[i][i] << ' ';
}
std::cout << std::endl;
std::cout.flush();
}
}
}
namespace solve_large {
struct debug {
int n;
std::vector<int> alb;
LL ask(int x, int y) {
return (LL) alb[x - 1] * alb[y - 1] / std::__gcd(alb[x - 1], alb[y - 1]);
}
debug() {
std::ifstream fin("a.in");
fin >> n;
for (int i = 1; i <= n; ++i) {
int xx;
fin >> xx;
alb.push_back(xx);
}
}
} deb;
#ifdef Debug
#define ask(x, y) deb.ask(x, y)
#endif
const int maxn = 200005;
LL ans[maxn];
int np[maxn];
std::mt19937 rnd(20030211u);
void Euler(const int n = 200000) {
std::vector<int> prime;
prime.clear();
for (int i = 2; i <= n; ++i) {
if (!np[i]) {
prime.push_back(i);
}
for (unsigned j = 0; j < prime.size() && (LL) i * prime[j] <= n; ++j) {
np[i * prime[j]] = true;
if (!(i % prime[j])) {
break;
}
}
}
}
void solve() {
std::vector<int> id;
id.clear();
for (int i = 1; i <= n; ++i) {
ans[i] = 0;
id.push_back(i);
}
std::shuffle(id.begin(), id.end(), rnd);
int qd = 0;
for (int i = 1; i <= 249 && i <= n; ++i) {
qd = id[i - 1];
for (int j = 1; j <= 20; ++j) {
int wz = rnd() % n + 1;
while (wz == qd) {
wz = rnd() % n + 1;
}
ans[qd] = std::__gcd(ask(qd, wz), ans[qd]);
if (ans[qd] <= 200000 && ans[qd] && !np[ans[qd]]) {
break;
}
}
if (ans[qd] && !np[ans[qd]] && ((ans[qd] << 1) > n)) {
break;
}
}
assert(ans[qd] <= 200000 && ans[qd] && !np[ans[qd]] && ((ans[qd] << 1) > n));
for (int i = 1; i <= n; ++i) {
if (!ans[i]) {
ans[i] = ask(i, qd) / ans[qd];
}
}
LL mx = 0;
int idd = 0;
for (int i = 1; i <= n; ++i) {
if (!np[ans[i]] && ans[i] >= mx) {
mx = ans[i];
idd = i;
}
}
for (int i = 1; i <= n; ++i) {
if (ans[i] == 2) {
ans[i] = ask(i, idd) / mx;
}
}
#ifndef Debug
std::cout << "! ";
#endif
for (int i = 1; i <= n; ++i) {
std::cout << ans[i] << ' ';
}
std::cout << std::endl;
std::cout.flush();
}
#ifdef Debug
#undef ask(x, y) deb.ask(x, y)
#endif
}
void solve() {
#ifndef Debug
std::cin >> n;
#else
n = solve_large::deb.n;
freopen("a.out", "w", stdout);
std::cout << n << std::endl;
#endif
if (n <= 100) {
solve_small::solve();
} else {
solve_large::solve();
}
}
int main() {
solve_large::Euler();
int T;
#ifndef Debug
std::cin >> T;
#else
T = 1;
#endif
while (T--) {
solve();
}
return 0;
}