1.​​题目链接​​。题目大意,有n个灯,它们围城一个圈,每个灯有两种状态,0代表灯没有开,1代表灯开着。现在做这样的调整,每一秒,我们检查这个灯的左边(就是逆时针相邻的那个点),如果左边的点是1,那么把该点的灯打开,否则不做变化。问T秒之后所有灯的状态。

2.这是一个矩阵的递推,我们这样考虑,a[i][j]代表第i秒这个点灯的状态,1就是开着,0就是关闭。那么我们在它的状态一定是这样来的:(a[i-1][j]+a[i-1][j-1])%2.就是上一轮这个点和它左边的点决定了此时的状态,那么,对于所有的灯,我们可以列出n个这样的方程,组成一个方程组,并且写成矩阵乘积的形式就是(用一个三维的矩阵为例子):

                                                                         【HDU2276】矩阵递推_#include*【HDU2276】矩阵递推_方程组_02=【HDU2276】矩阵递推_i++_03.

左边是初始的状态,右边是最终的结果,乘上转移矩阵即可。所以分析到这里,就是矩阵快速幂啦。问题解决。

#include<bits/stdc++.h>
#include<vector>
#include<string>
using namespace std;
struct Sarray
{
static const int LEN = 105;
static const int mod = 2;
int len, data[LEN][LEN];
Sarray(int len, int flag) :len(len) {
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++)data[i][j] = 0;
data[i][i] = flag;
}
}
Sarray() {};
Sarray operator *(const Sarray&a) {
Sarray tem(a.len, 0);
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
for (int k = 0; k < len; k++) {
tem.data[i][j] = (tem.data[i][j] + data[i][k] * a.data[k][j]) % mod;
}
}
}
return tem;
}

Sarray operator +(const Sarray&a) {
Sarray tem(a.len, 0);
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
tem.data[i][j] = (data[i][j] + a.data[i][j]) % mod;
}
}
return tem;
}

};

Sarray qpow(Sarray a, int b) {//会更改a,不能按引用传递
Sarray tem(a.len, 1);
while (b) {
if (b & 1)tem = a * tem;
a = a * a;
b >>= 1;
}
return tem;
}
Sarray ans;
int main()
{
int T;
string s;
while (cin >> T >> s)
{
int len = s.size();
Sarray trans(len, 0);
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
{
if (i == j)
{
trans.data[i][i] = 1;
trans.data[i][(i + 1)%len] = 1;
}
}
}
Sarray tem(len, 0);
for (int i = 0; i < s.size(); i++)
{
tem.data[0][i] = (s[i] - '0');
}
ans = tem * qpow(trans, T);
for (int i = 0; i < len; i++)
{
cout << ans.data[0][i];
}
cout << endl;
}
}