http://acm.hdu.edu.cn/showproblem.php?pid=2276

矩阵乘法可以解决的一类灯泡开关问题

/*
转移关系为 
now left now*
1    0    1 
1    1    0
0    1    1
0    0    0

可知F[i] = (f[i] + f[(n+i-2)%n+1]) % 2 
 
得到n*n的关系矩阵是
1 1 0 0 ... 0
0 1 1 0 ... 0
0 0 1 1 ... 0
. . . . ... 0
. . . . ... 0
. . . . ... 0
0 0 0 0 ... 1
1 0 0 0 ... 1
*/
#include <iostream> 
#include <cstdio>
#include <cstring>
#include <map>

using namespace std;

#define MOD 2

#define Mat 105 //矩阵大小
  
struct mat{//矩阵结构体,a表示内容,r行c列 矩阵从1开始  
    int a[Mat][Mat];
    int r, c;  
    mat() {  
        r = c = 0;  
        memset(a, 0, sizeof(a));  
    }  
};  

void print(mat m) {  
    //printf("%d\n", m.size);  
    for(int i = 0; i < m.r; i++) {  
        for(int j = 0; j < m.c; j++) printf("%d ", m.a[i][j]);  
        putchar('\n');  
    }  
}  
  
mat mul(mat m1, mat m2, int mod) {  
    mat ans  = mat();
    ans.r = m1.r, ans.c = m2.c;  
    for(int i = 1; i <= m1.r; i++)  
        for(int j = 1; j <= m2.r; j++)  
            if(m1.a[i][j])
                for(int k = 1; k <= m2.c; k++)  
                    ans.a[i][k] = (ans.a[i][k] + m1.a[i][j] * m2.a[j][k]) % mod;  
    return ans;  
} 

mat quickmul(mat m, int n, int mod) {  
    mat ans = mat();  
    for(int i = 1; i <= m.r; i++) ans.a[i][i] = 1;  
    ans.r = m.r, ans.c = m.c;  
    while(n) {  
        if(n & 1) ans = mul(m, ans, mod);  
        m = mul(m, m, mod);  
        n >>= 1;  
    }  
    return ans;  
}  

/* 
初始化ans矩阵 
mat ans = mat(); 
ans.r = R, ans.c = C;  
ans = quickmul(ans, n, mod); 
*/

char a[105];

int main() { 
    int m; 
    while(~scanf("%d", &m)) {
        scanf("%s", a);
        int n = strlen(a);
        mat A = mat();
        A.r = 1, A.c = n;
        for(int i = 1; i <= n; i++)
            A.a[1][i] = a[i-1] - '0';    
        mat G = mat();
        G.r = G.c = n;
        for(int i = 1; i < n; i++) {
            G.a[i][i] = G.a[i][i+1] = 1;
        }
        G.a[n][1] = G.a[n][n] = 1;
        mat ans = quickmul(G, m, MOD);
        ans = mul(A, ans, MOD);
        for(int i = 1; i <= n; i++)
            printf("%d", ans.a[1][i]);
        putchar('\n');
    }
    return 0;
}
View Code