1.题面
http://acm.hdu.edu.cn/showproblem.php?pid=2276
现在有围成圆圈的一圈灯,现在开始进行一系列的变换,变换的规则是,如果灯i的左边这盏灯是亮着的,那我们摁一下灯i的开关,也就是亮着的变成暗着的,暗着的变成亮着的。问m次变换之后的状态。
3.思路如果我们用1表示灯亮着,0代表灯暗着,数组a[n]来表示所有灯的状态,那么一次变换实际上可以视为a[i] = (a[i-1]+a[i])%2。
接下来只要构造矩阵就可以了,长度为n的数组对应于一个矩阵A,A的对角线和对角线左侧一个单位的地方是1,其余地方是0。
4.代码
代码丑成狗,瞎挂一下
template <class RandomAccessIterator>
void Print(RandomAccessIterator first, RandomAccessIterator last, char endl1='\n', char endl2=' '){
while (first != last)
cout << (*first++) << (last-1==first?endl1:endl2);
}
typedef long long ll;
const int matsize = 200;
int MOD = 2;
int n;
struct _matrix{
int m[matsize][matsize];
};
void printmatrix(_matrix q){
for (int i = 0; i < n; i++){
Print(q.m[i], q.m[i]+n, '\n', ' ');
}
}
_matrix operator * (const _matrix& a, const _matrix& b){
_matrix ret;
memset(ret.m, 0, sizeof(ret.m));
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (a.m[i][j] != 0){
for (int k = 0; k < n; k++){
ret.m[i][k] += a.m[i][j]*b.m[j][k];
ret.m[i][k] %= MOD;
}
}
}
}
return ret;
}
_matrix operator ^ (_matrix a, int p){
_matrix ret;
memset(ret.m, 0, sizeof(ret.m));
for (int i = 0; i < n; i++)
ret.m[i][i] = 1;
while (p > 0){
if (p&1){
ret = ret*a;
}
p >>= 1;
a = a*a;
}
return ret;
}
_matrix operator + (const _matrix& a, const _matrix& b){
_matrix ret;
memset(ret.m, 0, sizeof(ret.m));
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
ret.m[i][j] = (a.m[i][j] + b.m[i][j])%MOD;
}
}
return ret;
}
int main(){
// std::ios::sync_with_stdio(false);cin.tie(0);
int k;
char str[10000];
while (~scanf("%d", &k)){
scanf("%s", str);
n = strlen(str);
_matrix m;
memset(m.m, 0, sizeof(m.m));
for (int i = 0; i < n; i++){
m.m[i][(n+i-1)%n] = m.m[i][i] = 1;
}
m = m^k;
for (int i = 0; i < n; i++){
int sum = 0;
for (int j = 0; j < n; j++){
sum += str[j]=='1'&&m.m[i][j]==1;
}
printf("%d", sum&1);
}
printf("\n");
}
return 0;
}