bzoj 4417: [Shoi2013]超级跳马

来源:互联网 发布:三维动画演示软件 编辑:程序博客网 时间:2024/05/17 20:00

题意:现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角。每一步它向右跳奇数列,且跳到本行或相邻行。试求跳法种数mod 30011。
题解:DP+矩阵乘法+快速幂
f[i][j]表示走到第2i1列,第j行的方案数,g[i][j]表示走到第2i列,第j行的方案数。那么

f[i][j]=k=1i1g[k][j1]+k=1i1g[k][j]+k=1i1g[k][j+1]g[i][j]=k=1if[k][j1]+k=1if[k][j]+k=1if[k][j+1]
F[i][j]=ik=1f[k][j],G[i][j]=ik=1g[k][j]那么
F[i][j]=F[i1][j]+G[i1][j1]+G[i1][j]+G[i1][j+1]G[i][j]=G[i1][j]+F[i][j1]+F[i][j]+F[i][j+1]
矩阵推一推就出来了。
代码:

#include<bits/stdc++.h>using namespace std;struct matrix{    int x,y,a[110][110];    matrix()    {        memset(a,0,sizeof(a));        x=y=0;    }    int* operator[](int x)    {        return a[x];    }}a,b,one;int mod=30011,n,m;matrix operator*(matrix x,matrix y){    matrix ans;    ans.x=x.x;    ans.y=y.y;    for(int i=1;i<=ans.x;i++)    for(int j=1;j<=ans.y;j++)    for(int k=1;k<=x.y;k++)    ans[i][j]=(ans[i][j]+x[i][k]*y[k][j])%mod;    return ans;}matrix pow(matrix x,int y){    if(y==0)    return one;    else if(y==1)    return x;    matrix hh=pow(x,y>>1);    hh=hh*hh;    if(y&1)    hh=hh*x;    return hh;}int main(){    scanf("%d%d",&n,&m);    a.x=a.y=b.x=b.y=n<<1;    for(int i=1;i<=n;i++)    {        a[i][i]=a[n+i][n+i]=1;        if(i-1>0)        a[n+i-1][i]=1;        a[n+i][i]=1;        if(i+1<=n)        a[n+i+1][i]=1;    }    for(int i=1;i<=n;i++)    {        b[i][i]=b[n+i][n+i]=1;        if(i-1>0)        b[i-1][n+i]=1;        b[i][n+i]=1;        if(i+1<=n)        b[i+1][n+i]=1;    }/*    for(int i=1;i<=(n<<1);i++)    {        for(int j=1;j<=(n<<1);j++)        printf("%d ",a[i][j]);        puts("");    }    puts("");    for(int i=1;i<=(n<<1);i++)    {        for(int j=1;j<=(n<<1);j++)        printf("%d ",b[i][j]);        puts("");    }*/    for(int i=1;i<=(n<<1);i++)    one[i][i]=1;    one.x=one.y=n<<1;    a=a*b;    int hh=m+1>>1;    matrix ans;    ans.x=1;    ans.y=n<<1;    ans[1][1]=ans[1][n+1]=ans[1][n+2]=1;    if(hh<2)    {        if(m==1)        {            if(n==1)            puts("1");            else            puts("0");        }        else        {            if(n<=2)            puts("1");            else            puts("0");        }        return 0;    }    matrix c=pow(a,hh-2);    ans=ans*c;    matrix oo=ans*a;/*    for(int i=1;i<=(n<<1);i++)    printf("%d ",oo[1][i]);    puts("");    for(int i=1;i<=(n<<1);i++)    printf("%d ",ans[1][i]);    puts("");*/    if(m&1)    printf("%d",(oo[1][n]-ans[1][n]+mod)%mod);    else    printf("%d",(oo[1][n<<1]-ans[1][n<<1]+mod)%mod);}
原创粉丝点击