HDU2276 Kiki & Little Kiki 2 矩阵快速幂

来源:互联网 发布:埋点数据 编辑:程序博客网 时间:2024/06/01 09:50

HDU2276
题目是一个常见的一路路灯开开关关的问题,首先我们需要进行数学抽象1代表开灯,0代表关灯,整个路灯围成一个圆,并且当该路灯的左边的路灯是开着的,即1时,状态翻转,其余情况状态不变。题目中的m是108级的数据,模拟肯定会TLE。
分析状态变化的过程是思考题目重点:
首先路灯f(n)的t+1秒的状态是由f(n-1)与f(n)在第t秒的状态决定的。
讨论三个路灯之间的相互关系:

f(n-1) f(n) 下一秒的f(n) 0 0 0 1 0 1 0 1 1 1 1 0

由此可以得出关系为:f(n){t}=f(n-1){t-1}+f(n){t-1}
以样例1为例,就可以通过两个关系推出递推关系式:

f(0)f(1)f(2)f(3)f(4)f(5)f(6)=1100000011000000110000001100000011000000111000001mf(0)f(1)f(2)f(3)f(4)f(5)f(6)

在构造矩阵时有小技巧,上面矩阵就是m秒后的状态转移,通过矩阵快速幂能够迅速求出第m秒后相应的路灯的状态。
AC代码:

/*************************************************************** By: Xingxing* Date: 2016-09-26 23:33* Address: http://blog.csdn.net/legend_pawn?viewmode=contents**************************************************************/#include <iostream>#include <cstdio>#include <cstring>#include <cstring>using namespace std;const int N=100+5;int f[N];char s[N];int m,n;struct mat{    int m[N][N];    mat() {}    mat unit(){   //单位矩阵        for(int i=0;i<n;i++)            for(int j=0;j<n;j++)                m[i][j]=i==j?1:0;    }};mat t; //t为状态转移矩阵mat operator * (mat a,mat b){  //方阵乘法    mat res;    for(int i=0;i<n;i++)        for(int j=0;j<=n;j++){            res.m[i][j]=0;            for(int k=0;k<n;k++){                res.m[i][j]+=a.m[i][k]*b.m[k][j];                if(res.m[i][j]>=2)                    res.m[i][j]%=2;            }        }    return res;}mat operator ^ (mat res,int n){ //方阵二分幂    res.unit();    while(n>0){        if(n&1)            res=res*t;        n=n>>1;        t=t*t;    }    return res;}void init(){    memset(t.m,0,sizeof(t.m));    for(int i=0;i<n;i++)            if(i==0)                t.m[i][0]=t.m[i][n-1]=1;            else                t.m[i][i-1]=t.m[i][i]=1;}int main(){    //freopen("input.txt","r",stdin);    while(~scanf("%d",&m)){        mat ans,tmp;        scanf("%s",s);        n=strlen(s);        init();        for(int i=0;i<n;i++)            tmp.m[i][0]=s[i]-'0';        ans=t^(m);        /*for(int i=0;i<n;i++){            for(int j=0;j<n;j++)                printf("%d ",ans.m[i][j]);        cout<<endl;*/        ans=ans*tmp;        for(int i=0;i<n;i++)            printf("%d",ans.m[i][0]);        cout<<endl;    }    return 0;}
0 0
原创粉丝点击