[洛谷P3937]Changing
题目大意:有 $n$ 盏灯环形排列,顺时针依次标号为 $1\cdots n$。初始时刻为 $0$ ,初始时刻第 $i$ 盏灯的亮灭 $a_i$, $0$ 表示灭, $1$ 表示亮。下一时刻每盏灯的亮灭取决于当前时刻这盏灯与顺时针方向下一盏灯的亮灭。若两盏灯状态相同,则下一时刻该灯灭,否则该灯亮。试求时刻 $t$ 第 $k$ 盏灯的状态。
题解:时刻 $t$ 第 $k$ 盏灯的状态为
$$f_{t,k}=\left( \sum\limits_{i=0}^t C_t^i a_{(k+i-1) \bmod{(n+1)}}\right) \bmod{2}$$
$$\begin{align*}
\because f_{t,k}&=f_{t-1,k}\oplus f_{t-1,k+1}\\
&=(f_{t-1,k}+f_{t-1,k+1})\bmod{2}\\
&=(f_{t-2,k}+2\cdot f_{t-2,k+1}+f_{t-2,k+2})\bmod{2}\\
&=(f_{t-3,k}+3\cdot f_{t-3,k+1}+3\cdot f_{t-3,k+2}+f_{t-3,k+2})\bmod{2}\\
&\dots
\end{align*}$$
卡点:算一个数含有几个因数$2$时算错
C++ Code:
#include <cstdio> #define maxn 3000010 using namespace std; int count(int i) { int ans = 0, tmp = i & -i; while (tmp >>= 1) ans++; return ans; } int n, t, k, ans; int a[maxn], fac[maxn]; int C(int a, int b) {return fac[a] - fac[b] - fac[a - b] == 0;} int main() { scanf("%d%d%d", &n, &t, &k); for (int i = 0; i < n; i++) scanf("%d", &a[i]); k--; for (int i = 1; i <= t; i++) fac[i] = fac[i - 1] + count(i); for (int i = 0; i <= t; i++) { ans ^= C(t, i) & a[(k + i) % n]; } printf("%d\n", ans); return 0; }