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; }
时间: 2024-11-06 11:10:20