BZOJ 4417 超级跳马

Posted on 2016-09-28 20:31  ziliuziliu  阅读(295)  评论(0编辑  收藏  举报

dp前缀和优化+矩阵快速幂。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 110
#define mod 30011
using namespace std;
struct matrix
{
    int a[maxn][maxn];
}a,b;
int n,m,dp[maxn][5];
void get_table()
{
    for (int i=1;i<=n;i++) a.a[1][i]=dp[i][1];
    for (int i=1;i<=n;i++) a.a[1][n+i]=dp[i][2];
    for (int i=1;i<=n;i++) b.a[i+n][i]=1;
    for (int i=1;i<=n;i++) b.a[i][n+i]=b.a[max(n+i-1,n+1)][n+i]=b.a[n+i][n+i]=b.a[min(n+i+1,2*n)][n+i]=1;
}
matrix mul(matrix a,matrix b)
{
    matrix c;
    for (int i=1;i<=2*n;i++)
        for (int j=1;j<=2*n;j++)
            c.a[i][j]=0;
    for (int i=1;i<=2*n;i++)
        for (int j=1;j<=2*n;j++)
            for (int k=1;k<=2*n;k++)
                c.a[i][j]=(c.a[i][j]+(a.a[i][k]*b.a[k][j])%mod)%mod;
    return c;
}
void f_pow(int y)
{
    matrix base=b;
    while (y)
    {
        if (y&1) a=mul(a,base);
        base=mul(base,base);
        y>>=1;    
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    dp[1][1]=1;
    for (int i=1;i<=n;i++) dp[i][2]=(dp[i-1][1]+dp[i][1]+dp[i+1][1])%mod;
    for (int i=1;i<=n;i++) dp[i][3]=(dp[i-1][2]+dp[i][2]+dp[i+1][2]+dp[i][1])%mod;
    get_table();
    if (m==1) {if (n<=2) printf("1\n");else printf("0\n");return 0;}
    else if (m<=3) {printf("%d\n",(dp[n][m]-dp[n][m-2]+mod)%mod);return 0;}
    f_pow(m-3);
    int ret1,ret2;
    ret1=a.a[1][n];a=mul(a,b);ret2=a.a[1][2*n];
    printf("%d\n",(ret2-ret1+mod)%mod);
    return 0;
}