【题解】CF1624F Playing Around the Table
哈希表有一种简易的实现方式,求出 \(key = x\bmod P\),如果 \(hash_{key}\) 被占用了,那么就一直向后跳指针直到一个空的位置。
那么对于这题,我们可以用类似的思想,如果一个数归位了,那么就把它存下来,否则让它一直向后滚动直到某次可以存下它。
但是这样会遇到每个人 \(i\) 被还原的时候不同。那么如果 \(i\) 先被还原了,那么下一次滚动必然会破坏已经还原的状态。
换一种思路,我们先把每个人还原成 \(1\sim n\),那么如果一个人被还原了,接下来无论上家给自己什么,自己都可以吐出去相同的。
然后再把每个人还原,具体操作是枚举步长 \(l\),每次把玩家 \(i\) 前面 \(l\) 的人手上的 \(i\) 放在一轮一起还原。
#define N 105
int n, c[N][N], p[N], ans[N * N][N], t;
#define ck(x) (x > n ? (x - n) : x)
int main(){
read(n);
rp(i, n)rp(j, n){
int x; read(x);
c[i][x] ++;
}
while(true){
rp(i, n){
p[i] = 0;
rp(j, n)if(c[i][j] > 1)p[i] = j;
}
int w = 0;
rp(i, n)if(p[i])w = i;
if(!w)break;
rp(i, n){
int x = w == n ? 1 : w + 1;
if(!p[x])p[x] = p[w];
w = x;
}++t;
rp(i, n)ans[t][i] = p[i], c[i][p[i]]--, c[ck(i + 1)][p[i]]++;
}
pre(i, n, 2)rep(j, 1, n - i + 1){
++t;
rep(k, 1, n)ans[t][ck(i + j + k - 2)] = k;
}
printf("%d\n", t);
rp(i, t){rep(j, 1, n)printf("%d ", ans[i][j]); el;}
return 0;
}