hdoj 2276 Kiki & Little Kiki 2【矩阵快速幂】



Kiki & Little Kiki 2

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2302    Accepted Submission(s): 1177


Problem Description
There are n lights in a circle numbered from 1 to n. The left of light 1 is light n, and the left of light k (1< k<= n) is the light k-1.At time of 0, some of them turn on, and others turn off. 
Change the state of light i (if it's on, turn off it; if it is not on, turn on it) at t+1 second (t >= 0), if the left of light i is on !!! Given the initiation state, please find all lights’ state after M second. (2<= n <= 100, 1<= M<= 10^8)

 

Input
The input contains one or more data sets. The first line of each data set is an integer m indicate the time, the second line will be a string T, only contains '0' and '1' , and its length n will not exceed 100. It means all lights in the circle from 1 to n.
If the ith character of T is '1', it means the light i is on, otherwise the light is off.

 

Output
For each data set, output all lights' state at m seconds in one line. It only contains character '0' and '1.
 

Sample Input
       
       
       
       
1 0101111 10 100000001
 

Sample Output
       
       
       
       
1111000 001000010
 


感谢大排骨给我灵感,1A有大排骨的功劳。O(∩_∩)O~~


 

题意:给你N个围成一圈的灯,1号灯的左边是N号灯,N号灯的右边是1号灯。

这些灯的开关状态在时刻改变,这里给出第i个灯的变化规律(1表示该灯是开着的,0表示该灯是关着的

当第i个灯初始状态为1时,若它左边灯状态为1,则下一秒第i个灯状态变为0,反之不改变。

当第i个灯初始状态为0时,若它左边灯状态为1,则下一秒第i个灯状态变为1,反之不改变。

已经给你这N个灯的状态,问你m秒后这N个灯的状态。

 

 

分析:m = 10^8,显然不能模拟,只能用矩阵做。找出前后两个状态之间的联系,构造出矩阵就可以了。


对第i个灯,下一秒它的状态改变只取决于它左边灯的状态A和自己的状态B,其它灯不会影响到第i个灯状态的改变。

这样我们只需要求出A和B就可以了,至于其它灯的状态可以全看做0。这个用矩阵很好实现。

比如说,我们想要第i个灯的状态,只需要把第i个灯在矩阵的相应位置赋值为1。把其它灯的状态看做0更简单,把矩阵中其它灯的对应位置赋值为0。

对AB以及相应的B的改变,则有4种可能:(1) 01 -> 1; (2) 10 -> 1;(3) 00 ->0 (4) 11 -> 0。

这里不要想远了,不要想什么异或,我就是想到异或才卡了一会。 

好好思考下,会发现这是两数之和对2取余后的结果(一开始想到了,没去模拟结果o(╯□╰)o)。


给个图示矩阵:

结果                  初始矩阵                        F矩阵

hdoj 2276 Kiki & Little Kiki 2【矩阵快速幂】_第1张图片



构造好初始矩阵,求出m次幂(注意对2取余),再与F矩阵相乘对2取余。


AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 110
#define LL long long
using namespace std;
struct Matrix
{
    int a[MAXN][MAXN];
    int r, c;
};
Matrix ori, res;
int F[MAXN];//F矩阵
void init(char *s)
{
    int len = strlen(s);
    ori.r = ori.c = len;//初始矩阵
    res.r = res.c = len;//单位矩阵
    memset(ori.a, 0, sizeof(ori.a));
    memset(res.a, 0, sizeof(res.a));
    for(int i = 0; i < len; i++)
    {
        int k = s[i] - '0';
        F[i] = k;
        ori.a[i][i] = res.a[i][i] = 1;
        if(i == 0)
            ori.a[i][len-1] = 1;
        else
            ori.a[i][i-1] = 1;
    }
}
Matrix muitl(Matrix x, Matrix y)
{
    Matrix z;
    memset(z.a, 0, sizeof(z.a));
    z.r = x.r, z.c = y.c;
    for(int i = 0; i < x.r; i++)
    {
        for(int k = 0; k < x.c; k++)
        {
            if(x.a[i][k] == 0) continue;
            for(int j = 0; j < y.c; j++)
                z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % 2;
        }
    }
    return z;
}
void Matrix_mod(int n)
{
    while(n)
    {
        if(n & 1)
            res = muitl(ori, res);
        ori = muitl(ori, ori);
        n >>= 1;
    }
}
int Ans[MAXN];
void solve(int n)
{
    Matrix_mod(n);
    memset(Ans, 0, sizeof(Ans));
    for(int i = 0; i < res.r; i++)
    {
        for(int k = 0; k < res.c; k++)
        {
            if(res.a[i][k] == 0) continue;
            Ans[i] = (Ans[i] + res.a[i][k] + F[k]) % 2;
        }
    }
    for(int i = 0; i < res.r; i++)
        printf("%d", Ans[i]);
    printf("\n");
}
int main()
{
    int m;
    char str[110];
    while(scanf("%d", &m) != EOF)
    {
        scanf("%s", str);
        init(str);//构造矩阵
        solve(m);
    }
    return 0;
}


你可能感兴趣的:(hdoj 2276 Kiki & Little Kiki 2【矩阵快速幂】)