题目链接:https://codeforces.com/contest/1569/problem/E
如果有 \(2^k\) 个参赛选手,那么一共会进行 \(2^k-1\) 场比赛,搜索每场比赛的结果,判断是否满足条件就可以了,但当 \(k=5\) 时,\(2^5=32\),爆搜显然不行,可以使用 \(meet-in-the-middle\) 的技巧,将所有参赛队员分为两组,组内分别搜索,记录第一组所有的答案,第二组搜索时在第一组的答案中查询即可
具体实现还有很多细节
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 155;
const int M = 998244353;
const int base = 131;
int n, k, A, h, tot, flag, f1, f2, t1, t2;
int p[10], a[maxn][10], rk[maxn], c[maxn];
map<int, int> mp;
int qsm(int i, int po){
int res = 1;
while(po){
if(po & 1) res = 1ll * res * i % M;
i = 1ll * i * i % M;
po >>= 1;
}
return res;
}
int get_r(int d){
int tmp = d, r = k-2;
for(int i = k-2 ; i >= 0 ; --i){
if(tmp - (1<<i) > 0) {
tmp -= (1<<i);
--r;
}
else break;
}
return r;
}
void dfs1(int d, int H){
if(d == (1<<(k-1))){
rk[c[2*d-1]] = p[1];
int hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*i*qsm(A,rk[i])%M) % M;
if(mp.count(hh) == 0) mp[hh] = 1;
rk[c[2*d-1]] = p[2];
hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*i*qsm(A,rk[i])%M) % M;
if(mp.count(hh) == 0) mp[hh] = 1;
return;
}
++tot;
int pos = tot;
c[pos] = c[2*d-1];
int r = get_r(d);
rk[c[2*d]] = r != -1 ? p[r+3] : 3;
dfs1(d+1, (H + a[c[2*d]][r+3]) % M);
rk[c[2*d]] = 0;
c[pos] = c[2*d];
rk[c[2*d-1]] = r != -1 ? p[r+3] : 3;
dfs1(d+1, (H + a[c[2*d-1]][r+3]) % M);
rk[c[2*d-1]] = 0;
--tot;
}
void dfs2(int d, int H){
if(flag) return;
if(d == (1<<(k-1))){
rk[c[2*d-1]] = p[1];
int hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*(i+(1<<k-1))*qsm(A,rk[(i+(1<<k-1))])%M) % M;
if(mp.count(((h-hh)%M+M)%M) != 0) {
f1 = ((h-hh)%M+M)%M, f2 = hh;
flag = 1; return;
}
rk[c[2*d-1]] = p[2];
hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*(i+(1<<k-1))*qsm(A,rk[(i+(1<<k-1))])%M) % M;
if(mp.count(((h-hh)%M+M)%M) != 0) {
f1 = ((h-hh)%M+M)%M, f2 = hh;
flag = 1; return;
}
return;
}
++tot;
int pos = tot;
c[pos] = c[2*d-1];
int r = get_r(d);
rk[c[2*d]] = r != -1 ? p[r+3] : 3;
dfs2(d+1, (H + a[c[2*d]][r+3]) % M);
rk[c[2*d]] = 0;
c[pos] = c[2*d];
rk[c[2*d-1]] = r != -1 ? p[r+3] : 3;
dfs2(d+1, (H + a[c[2*d-1]][r+3]) % M);
rk[c[2*d-1]] = 0;
--tot;
}
void find1(int d, int H){
if(t1) return;
if(d == (1<<(k-1))){
rk[c[2*d-1]] = p[1];
int hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*i*qsm(A,rk[i])%M) % M;
if(hh == f1){
t1 = 1;
for(int i = 1 ; i <= (1<<k-1) ; ++i) printf("%d ", rk[i]);
return;
}
rk[c[2*d-1]] = p[2];
hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*i*qsm(A,rk[i])%M) % M;
if(hh == f1){
t1 = 1;
for(int i = 1 ; i <= (1<<k-1) ; ++i) printf("%d ", rk[i]);
return;
}
return;
}
++tot;
int pos = tot;
c[pos] = c[2*d-1];
int r = get_r(d);
rk[c[2*d]] = r != -1 ? p[r+3] : 3;
find1(d+1, (H + a[c[2*d]][r+3]) % M);
rk[c[2*d]] = 0;
c[pos] = c[2*d];
rk[c[2*d-1]] = r != -1 ? p[r+3] : 3;
find1(d+1, (H + a[c[2*d-1]][r+3]) % M);
rk[c[2*d-1]] = 0;
--tot;
}
void find2(int d, int H){
if(t2) return;
if(d == (1<<(k-1))){
rk[c[2*d-1]] = p[1];
int hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*(i+(1<<k-1))*qsm(A,rk[(i+(1<<k-1))])%M) % M;
if(hh == f2){
t2 = 1;
for(int i = 1 ; i <= (1<<k-1) ; ++i) printf("%d ", rk[i+(1<<k-1)]);
return;
}
rk[c[2*d-1]] = p[2];
hh = 0;
for(int i = 1 ; i <= (1<<k-1) ; ++i) hh = (hh + 1ll*(i+(1<<k-1))*qsm(A,rk[(i+(1<<k-1))])%M) % M;
if(hh == f2){
t2 = 1;
for(int i = 1 ; i <= (1<<k-1) ; ++i) printf("%d ", rk[i+(1<<k-1)]);
return;
}
return;
}
++tot;
int pos = tot;
c[pos] = c[2*d-1];
int r = get_r(d);
rk[c[2*d]] = r != -1 ? p[r+3] : 3;
find2(d+1, (H + a[c[2*d]][r+3]) % M);
rk[c[2*d]] = 0;
c[pos] = c[2*d];
rk[c[2*d-1]] = r != -1 ? p[r+3] : 3;
find2(d+1, (H + a[c[2*d-1]][r+3]) % M);
rk[c[2*d-1]] = 0;
--tot;
}
void print(){
t1 = 0, t2 = 0;
tot = (1<<(k-1));
for(int i = 1 ; i <= tot ; ++i) c[i] = i;
find1(1, 0);
for(int i = 1 ; i <= tot ; ++i) c[i] = i+tot;
find2(1, 0);
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
flag = 0;
memset(rk, 0, sizeof(rk));
k = read(), A = read(), h = read();
p[1] = 1, p[2] = 2, p[3] = 3, p[4] = 5, p[5] = 9, p[6] = 17;
for(int i = 1 ; i <= (1<<k) ; ++i){
for(int j = 1 ; j <= 6 ; ++j){
a[i][j] = 1ll * i * qsm(A, p[j]) % M;
}
}
n = (1<<k);
tot = (1<<(k-1));
for(int i = 1 ; i <= tot ; ++i) c[i] = i;
dfs1(1, 0);
for(int i = 1 ; i <= tot ; ++i) c[i] = i+tot;
dfs2(1, 0);
if(!flag) printf("-1\n");
else print();
return 0;
}