题意:给出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;
}