int a[N], b[N]; bool aa[N], bb[N], key; //在a中某一个数是否被使用过 int n, m, cnt, dx, dy; int x[G], y[G], head[N];
int re[30][30]; //对应关系, re[i][j]表示a[i]对应的b[(a[i]+j)%m]等于多少
voidPrint_res() { for (int i = 0; i < m; i ++) printf("%d ", a[i]); printf("\n"); for (int i = 0; i < m; i ++) printf("%d ", b[i]); return; }
voiddfs(int t)//在a中填数,记录a[]与b[]的对应关系,在a中填一个数就把有对应关系的数全部填上 { if (t == m) return (void)(key = 1, Print_res()); for (int k = 0; k < m; k ++) { if (aa[k]) continue; a[t] = k; bool ok = 1; //填这个数是否可行 bool temp[30] = {0}; //记录哪些数是这一次新填入的 回溯时便于区分 for (int e = 0; e < m; e ++) { if (re[t][e] == -1) continue; int v = (a[t] + e) % m; int val = re[t][e]; //要填的数 //先看能不能填这个数 先不要往里面填数 if ((b[v] == -1 && bb[val] == 0) || b[v] == val); else {ok = 0;break;} } /* printf("在第%d位上填%d ok=%d ",t,k,ok); printf("a="); for (int i=0;i<m;i++) printf("%d ",a[i]); printf("b="); for (int i=0;i<m;i++) printf("%d ",b[i]); printf("\n"); */ if (ok == 0) continue; aa[k] = 1; for (int e = 0; e < m; e ++) { if (re[t][e] == -1) continue; int v = (a[t] + e) % m; int val = re[t][e]; if (b[v] == -1) { b[v] = val; bb[val] = 1; temp[v] = 1; //说明这个数是这次新填入的 } } dfs(t + 1); if (key) return; for (int i = 0; i < m; i ++) { if (temp[i]) { bb[b[i]] = 0; b[i] = -1; //回溯 删除这一次新填的数 但是不能删除以前填过的而在这一次又满足条件的数 } } aa[k] = 0; } return; }
signedmain() { n = read(), m = read(); for (int i = 1; i <= n; i ++) x[i] = read(); for (int i = 1; i <= n; i ++) y[i] = read(); for (int i = 0; i < m; i ++) a[i] = b[i] = -1; //未填数 memset(re, -1, sizeof(re)); while (cnt < n) { ++ cnt; re[(x[cnt] + dx) % m][dy] = y[cnt]; ++ dx; if (dx == m) dx = 0, ++ dy; if (dy == m) dy = 0; } dfs(0); return0; }