HDU 2276 Kiki & Little Kiki 2

HDU_2276

    这个题让我联想到了最近刚学的数电的时序逻辑电路……

    当前这个灯的状态取决于上一时刻左边的灯的状态以及自己的状态,枚举情况之后就会得到00->?0,01->?1,10->?1,11->?0,如果我们设f[i][j]表示i时刻第j个灯的状态,1表示亮,那么根据上面4种情况就可以得到f[i][j]=(f[i-1][j-1]+f[i-1][j])%2,这样我们根据递推公式构造矩阵后用二分矩阵的方法就可以快速求出最终的各个灯的状态了。

#include<stdio.h>

#include<string.h>

#define MAXD 110

int N, M, cnt, a[MAXD];

char b[MAXD];

struct Matrix

{

    int a[MAXD][MAXD];

    void init()

    {

        int i;

        memset(a, 0, sizeof(a));

        a[0][0] = a[0][N - 1] = 1;

        for(i = 1; i < N; i ++)

            a[i][i] = a[i][i - 1] = 1;

    }

}mat[150];

int multiply(int x, int y)

{

    int i, j, k, z = ++ cnt, ans;

    memset(mat[z].a, 0, sizeof(mat[z].a));

    for(i = 0; i < N; i ++)

        for(k = 0; k < N; k ++)

            if(mat[x].a[i][k])

            {

                for(j = 0; j < N; j ++)

                    if(mat[y].a[k][j])

                        mat[z].a[i][j] = (mat[z].a[i][j] + mat[x].a[i][k] * mat[y].a[k][j]) & 1;

            }

    return z;

}

int powmod(int n)

{

    int k;

    if(n == 1)

        return 0;

    k = powmod(n >> 1);

    k = multiply(k, k);

    if(n & 1)

        k = multiply(k, 0);

    return k;

}

void solve()

{

    int i, j, k, ans;

    scanf("%s", b);

    for(i = 0; b[i]; i ++)

        a[i] = b[i] - '0';

    N = i;

    mat[cnt = 0].init();

    k = powmod(M);

    for(i = 0; i < N; i ++)

    {

        ans = 0;

        for(j = 0; j < N; j ++)

            ans += mat[k].a[i][j] * a[j];

        printf("%d", ans & 1);

    }

    printf("\n");

}

int main()

{

    while(scanf("%d", &M) == 1)

    {

        solve();

    }

    return 0;

}

你可能感兴趣的:(HDU)