题意:给出n个灯的状态’1’表示开,’0’表示关,现在给出一个规则,如果这个灯的左边的灯是开的(第一个灯的左边的灯是最后一个),那么就可以改变自己的状态,比如之前是1后来变0,之前是0后来变1,问m轮后n个灯的状态。
题解:第一个矩阵是当前灯的状态,第二个矩阵的每列就把当前行和前一行标记1,其他标记0,当前灯的状态其实就是当前灯状态和前一个灯状态的异或操作,在矩阵乘法时相加模2就是结果。
#include <stdio.h>
#include <string.h>
const int N = 105;
struct Mat {
int g[N][N];
}ori, res;
char str[N];
int n, m;
Mat multiply(Mat x, Mat y) {
Mat temp;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
temp.g[i][j] = 0;
for (int k = 0; k < n; k++)
temp.g[i][j] = (temp.g[i][j] + x.g[i][k] * y.g[k][j]) % 2;
}
return temp;
}
void calc(int m) {
while (m) {
if (m & 1)
ori = multiply(ori, res);
m >>= 1;
res = multiply(res, res);
}
}
int main() {
while (scanf("%d", &m) == 1) {
memset(res.g, 0, sizeof(res.g));
memset(ori.g, 0, sizeof(ori.g));
scanf("%s", str);
n = strlen(str);
for (int i = 0; i < n; i++)
ori.g[0][i] = str[i] - '0';
for (int i = 0; i < n; i++)
res.g[i][i] = res.g[i][(i + 1) % n] = 1;
calc(m);
for (int i = 0; i < n; i++)
printf("%d", ori.g[0][i]);
printf("\n");
}
return 0;
}