【[Offer收割]编程练习赛13 D】骑士游历(矩阵模板,乘法,加法,乘方)

【题目链接】:http://hihocoder.com/problemset/problem/1504

【题意】

【题解】

可以把二维的坐标转成成一维的;
即(x,y)->(x-1)*8+y
然后就写矩阵乘法吧。
每个点每次能够到达的点是固定的;
把每个点能够到达的点写成一个矩阵的形式;
作为系数矩阵;
求它的n次方
然后初始矩阵a[(r,c)][(r,c)]=1
用它去左乘系数矩阵;
就能得到到每个点的方案数了;
肯定都是不同的方案
直接累计答案就好;
最后注意是枚举到64而不是8了!!

【Number Of WA

0

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define ps push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x)
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,-2,-1,1,2,2,1,-1,-2};
const int dy[9] = {0,-1,-2,-2,-1,1,2,2,1};
const double pi = acos(-1.0);
const int N = 110;

const int G = 64;       //矩阵大小
const int MOD = 1e9 + 7;    //模数
struct MX
{
    int v[G+5][G+5];
    void O() { ms(v, 0); }
    void E() { ms(v, 0); for (int i = 1; i <= G; ++i)v[i][i] = 1; }
    void P()
    {
        for (int i = 1; i <= G; ++i)
        {
            for (int j = 1; j <= G; ++j)printf("%d ", v[i][j]); puts("");
        }
    }
    MX operator * (const MX &b) const
    {
        MX c; c.O();
        for (int k = 1; k <= G; ++k)
        {
            for (int i = 1; i <= G; ++i) if (v[i][k])
            {
                for (int j = 1; j <= G; ++j)
                {
                    c.v[i][j] = (c.v[i][j] + (LL)v[i][k] * b.v[k][j]) % MOD;
                }
            }
        }
        return c;
    }
    MX operator + (const MX &b) const
    {
        MX c; c.O();
        for (int i = 1; i <= G; ++i)
        {
            for (int j = 1; j <= G; ++j)
            {
                c.v[i][j] = (v[i][j] + b.v[i][j]) % MOD;
            }
        }
        return c;
    }
    MX operator ^ (LL p) const
    {
        MX y; y.E();
        MX x; memcpy(x.v, v, sizeof(v));
        int num[64+2],cnt = 0;
        while (p)
        {
            num[++cnt] = p&1;
            p>>=1;
        }
        for (int i =cnt;i>=1;i--)
        {
            y = y*y;
            if (num[i])
                y = y*x;
        }
        return y;
    }
}a,xishu;

int change(int x,int y)
{
    return (x-1)*8+y;
}

int n,r,c;

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    xishu.O();
    rep1(i,1,8)
        rep1(j,1,8)
        {
            rep1(k,1,8)
            {
                int x = i+dx[k],y = j+dy[k];
                if (x>=1 && x<=8 && y>=1 && y <=8)
                {
                    xishu.v[change(i,j)][change(x,y)] = 1;
                }
            }
        }
    rei(n),rei(r),rei(c);
    a.O();
    a.v[change(r,c)][change(r,c)] = 1;
    a = a*(xishu^n);
    int ans = 0;
    rep1(i,1,G)
        rep1(j,1,G)
        {
            ans = ans+a.v[i][j];
            if (ans>=MOD) ans-=MOD;
        }
    printf("%d\n",ans);
    //printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(109)  评论(0编辑  收藏  举报