首页 > 代码库 > HDU2276 - Kiki & Little Kiki 2(矩阵快速幂)

HDU2276 - Kiki & Little Kiki 2(矩阵快速幂)

题目链接


题意:有n盏灯,编号从1到n。他们绕成一圈,也就是说,1号灯的左边是n号灯。如果在第t秒的时候,某盏灯左边的灯是亮着的,那么就在第t+1秒的时候改变这盏灯的状态。输入m和初始灯的状态。输出m秒后,所有灯的状态。

思路:其实每盏灯的状态之和前一盏和自己有关,所以可以得到一个关系矩阵。假设有6盏灯,因此可以得到关系矩阵如下: 
(1, 0, 0, 0, 0, 1) 
(1, 1, 0, 0, 0, 0) 
(0, 1, 1, 0, 0, 0) 
(0, 0, 1, 1, 0, 0) 
(0, 0, 0, 1, 1, 0) 
(0, 0, 0, 0, 1, 1) 
这样的话就可以以此类推,得到n盏灯时的关系矩阵,然后使用矩阵快速幂进行运算。

PS:在这里,自己刚开始快速幂是用递归的,但是暴栈了。。。后来改成非递归才过的。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

const int MAXN = 105;

struct mat{
    int s[MAXN][MAXN];
    int l;
    mat(int len) {
        memset(s, 0, sizeof(s)); 
        l = len;
    }
    mat operator * (const mat& c) {
        mat ans(l); 
        memset(ans.s, 0, sizeof(ans.s)); 
        for (int i = 0; i < l; i++)
            for (int j = 0; j < l; j++) {
                for (int k = 0; k < l; k++)
                    ans.s[i][j] = (ans.s[i][j] + s[i][k] * c.s[k][j]);
                ans.s[i][j] = ans.s[i][j] % 2;
            }
        return ans;
    }
};

char str[MAXN];
int t;

mat pow_mod(mat c, int k) {
    /*if (k == 1)
        return c; 
    mat a = pow_mod(c, k / 2); 
    mat ans = a * a;
    if (k % 2)
        ans = ans * c;
    return ans;*/
    mat ans = c;
    k--;
    while (k) {
        if (k & 1) 
            ans = ans * c;
        k >>= 1;
        c = c * c;
    }
    return ans;
}

int main() {
    while (scanf("%d", &t) != EOF) {
        scanf("%s", str); 
        int l = strlen(str);
        mat c(l);
        for (int i = 0; i < l; i++)
            for (int j = 0; j < l; j++) {
                if (i == 0) 
                    c.s[i][0] = c.s[i][l - 1] = 1;
                else
                    c.s[i][i - 1] = c.s[i][i] = 1;
            }
        mat tmp(l);
        for (int i = 0; i < l; i++)
            tmp.s[i][0] = str[i] - '0';
        mat ans = pow_mod(c, t);
        ans = ans * tmp;
        for (int i = 0; i < l; i++)
            printf("%d", ans.s[i][0]);
        printf("\n");
    }
    return 0;
}


HDU2276 - Kiki & Little Kiki 2(矩阵快速幂)