2 n 2n 2n个位置,一开始奇数位置上有 n n n个硬币,依次给出每个硬币是正面还是反面,正面为 1 1 1,反面为 2 2 2。其他位置为 0 0 0,即没有硬币存在。
有 m m m次操作,每次操作为:
在任意两个硬币之间放上一个硬币,然后将原来的硬币拿走;
所放硬币的正反面由它两边的两个硬币决定,若两个硬币均为正面朝上或反面朝上,则所放硬币为正面朝上,否则为反面朝上。
问操作 m m m次之后 2 n 2n 2n个位置上对应的硬币的放置状态,空的输出 0 0 0,有硬币的话,硬币是正面输出 1 1 1,反面输出 2 2 2
n < = 100000 , m < = 2 60 n<=100000,m<=2^{60} n<=100000,m<=260
不难发现题目中的每2次操作以后,都是回到初始状态的位置
回到初始状态的位置,即如果你当前是1,3,5,7……的位置,那么下次就是偶数位置序列,再下次就还是现在的奇数位置序列
而对于当前经过2次操作以后的新的硬币摆放状态,
根据在 x o r xor xor运算中,
0 0 0 xor 1 = 1 , 1 1=1,1 1=1,1 x o r xor xor 0 = 1 , 0 0=1,0 0=1,0 x o r xor xor 0 = 0 , 1 0=0,1 0=0,1 x o r xor xor 1 = 0 1=0 1=0
把正面设为 0 0 0,反面设为 1 1 1,
不难发现都是对经过2次操作之前的硬币摆放状态中相邻2个数求一个 x o r 和 xor和 xor和,然后重新构成的状态
然后我们可以发现对于当前硬币状态 x x x,
经过 2 ∗ 2 k 2*2^k 2∗2k次操作以后的硬币摆放状态 y y y,
y y y中的第 i i i个元素即为 x x x中的第 i − 2 k i-2^k i−2k个数 x o r xor xor上第 i + 2 k i+2^k i+2k个数 (注意这是首尾相连的序列)
证明如下,
设 k = x k=x k=x的时候
满足当前序列 y y y跟 2 ∗ 2 x 2*2^{x} 2∗2x次操作之前的序列 X Y XY XY,每个 y i = X Y i − 2 x y_i=XY_{i-2^x} yi=XYi−2x x o r xor xor X Y i + 2 x XY_{i+2^x} XYi+2x
那么当 k = x + 1 k=x+1 k=x+1的时候
设当前序列为 z z z,
则 X Y XY XY为 z z z在 2 ∗ 2 x + 1 2*2^{x+1} 2∗2x+1次操作之前的序列
而 y y y为 z z z在 2 ∗ 2 x 2*2^{x} 2∗2x次操作之前的序列
如果我把 y y y当成初始序列,
那么此时的 k ′ = k − 1 = x + 1 − 1 = x k'=k-1=x+1-1=x k′=k−1=x+1−1=x,显然我们已经确定 k ′ = x k'=x k′=x是满足的,
所以此时每个 z i = y i − 2 x z_i=y_{i-2^x} zi=yi−2x x o r xor xor y i + 2 x y_{i+2^x} yi+2x
因为每个 y i = X Y i − 2 x y_i=XY_{i-2^x} yi=XYi−2x x o r xor xor X Y i + 2 x XY_{i+2^x} XYi+2x
所以每个 z i = ( X Y i − 2 x − 2 x z_i=(XY_{i-2^x-2^x} zi=(XYi−2x−2x x o r xor xor X Y i − 2 x + 2 x ) XY_{i-2^x+2^x}) XYi−2x+2x) x o r xor xor ( X Y i + 2 x − 2 x (XY_{i+2^x-2^x} (XYi+2x−2x x o r xor xor X Y i + 2 x + 2 x ) XY_{i+2^x+2^x}) XYi+2x+2x)
然后归纳一下可以得到
z i = X Y i − 2 x + 1 z_i=XY_{i-2^{x+1}} zi=XYi−2x+1 x o r xor xor X Y i + 2 x + 1 = X Y i − 2 k XY_{i+2^{x+1}}=XY_{i-2^k} XYi+2x+1=XYi−2k x o r xor xor X Y i + 2 k XY_{i+2^k} XYi+2k
证毕
那么我们对 m / 2 m/2 m/2进行2进制拆分然后搞一下就可以了,注意一开始如果 m m m是奇数就先把序列翻一遍然后再做。
P S : 不 能 输 出 行 末 空 格 , 否 则 据 说 会 有 点 难 受 PS:不能输出行末空格,否则据说会有点难受 PS:不能输出行末空格,否则据说会有点难受
#include
#include
#include
#include
#include
#include
#include
#define mp(x, y) memcpy(x, y, sizeof(y))
#define N 100005
using namespace std;
typedef long long ll;
int NowNum[N], A[N], n;
ll cdp, m;
int main()
{
scanf("%d %lld", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &A[i]), -- A[i];
if (m % 2)
{
for (int i = 1; i <= n; i++) NowNum[i] = A[i] ^ A[i % n + 1];
mp(A, NowNum);
}
cdp = m / 2;
for (; cdp;)
{
ll x = cdp & (- cdp);
for (int i = 1; i <= n; i++)
{
int l = i - ll(x % n); if (l < 1) l += n;
int r = i + ll(x % n); if (r > n) r -= n;
NowNum[i] = A[l] ^ A[r];
}
mp(A, NowNum);
cdp = cdp - x;
}
if (m % 2) { for (int i = 1; i < n; i++) printf("0 %d ", A[i] + 1); printf("0 %d", A[n] + 1); }
else { for (int i = 1; i < n; i++) printf("%d 0 ", A[i] + 1); printf("%d 0", A[n] + 1); }
return 0;
}