zoukankan      html  css  js  c++  java
  • ACdream1093

    给你三种正多面体,正四面体,正六面体,正八面体。求从某一种正多面体中的某一点走到另一个点,且步数不超过k(1018)的方案数。

    首先说明一下我交题的时候遇到的问题,起点和终点为同一点的时候,算不算走了零步到达了?题目没有算,如果考虑了交上去会wa。

    题目解法是矩阵。

    一开始通过观察这三种多面体,得出初始矩阵。 这里要细心。

    显然我们可以通过矩阵乘法迅速地知道从一点到另一点走k步的方案数。假设矩阵是a[][],那么x->y的方案就是a[x][y]。

    要求不超过k步的方案,就相当于前k个矩阵求和了(前k次方和)。因为矩阵有很多性质跟数是一样的,我们可以用类似的方法求解。

    我也不知道自己用的是什么方法,反正这样写可以过。不过好像时间上不是最优的。

    召唤代码君:

    /*
    * this code is made by 092000
    * Problem: 1093
    * Verdict: Accepted
    * Submission Date: 2014-07-20 10:06:15
    * Time: 592MS
    * Memory: 1676KB
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    typedef long long ll;
    using namespace std;
     
    const int mod=1000000007;
    ll k;
    int n,I,J,T;
     
    int a4[4][4]={
            {0,1,1,1},
            {1,0,1,1},
            {1,1,0,1},
            {1,1,1,0},
        };
         
    int a6[6][6]={
            {0,1,1,1,1,0},
            {1,0,1,0,1,1},
            {1,1,0,1,0,1},
            {1,0,1,0,1,1},
            {1,1,0,1,0,1},
            {0,1,1,1,1,0},
    };
         
    int a8[8][8]={
            {0,1,0,1,1,0,0,0},
            {1,0,1,0,0,1,0,0},
            {0,1,0,1,0,0,1,0},
            {1,0,1,0,0,0,0,1},
            {1,0,0,0,0,1,0,1},
            {0,1,0,0,1,0,1,0},
            {0,0,1,0,0,1,0,1},
            {0,0,0,1,1,0,1,0},
    };
     
    struct mat{
        ll a[8][8];
        void init0()
            {
                memset(a,0,sizeof a);
            }
        void init1()
            {
                init0();
                for (int i=0; i<n; i++) a[i][i]=1;
            }
        void init(int x)
        {
            init0();
            if (x==4)
            {
                for (int i=0; i<4; i++)
                    for (int j=0; j<4; j++) a[i][j]=a4[i][j];
            }
            else if (x==6)
            {
                for (int i=0; i<6; i++)
                    for (int j=0; j<6; j++) a[i][j]=a6[i][j];
            }
            else
            {
                for (int i=0; i<8; i++)
                    for (int j=0; j<8; j++) a[i][j]=a8[i][j];
            }
        }
    };
     
    mat add(mat e1,mat e2)
    {
        mat e0;
        for (int i=0; i<n; i++)
            for (int j=0; j<n; j++)
                e0.a[i][j]=(e1.a[i][j]+e2.a[i][j])%mod;
        return e0;
    }
     
    mat mul(mat e1,mat e2)
    {
        mat e0;
        e0.init0();
        for (int i=0; i<n; i++)
            for (int j=0; j<n; j++)
                for (int k=0; k<n; k++) e0.a[i][j]=(e0.a[i][j]+e1.a[i][k]*e2.a[k][j])%mod;
        return e0;
    }
     
    mat power(mat e,ll y)
    {
        mat e0;
        e0.init1();
        while (y)
        {
            if (y&1) e0=mul(e0,e);
            e=mul(e,e),y>>=1;
        }
        return e0;
    }
     
    int main()
    {
        mat ans,tmp,squ,E;
        ll answer;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d",&n);
            scanf("%lld",&k);
            scanf("%d",&I);
            scanf("%d",&J);
            //scanf("%d%lld%d%d",&n,&k,&I,&J);
            if (n==8) n=6;
                else if (n==6) n=8;
            ans.init0();
            tmp.init1();
            squ.init1();
            E.init(n);
            while (k)
            {
                if (k&1) ans=add(ans,mul(tmp,power(E,k)));
                k>>=1;
                tmp=mul(tmp,add(power(E,k),squ));
            }
            answer=ans.a[I-1][J-1];
            //if (I==J) answer++;
            answer%=mod;
            printf("%d
    ",(int)answer);
        }
        return 0;
    }
    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    python simplejson and json 使用及区别
    python 网页抓取并保存图片
    word2vec剖析,资料整理备存
    centos 安装LAMP环境后装phpmyadmin
    centos 安装卸载软件命令 & yum安装LAMP环境
    Ubuntu终端快捷键使用
    Ubuntu终端文件的压缩和解压缩命令
    文本预处理去除标点符号
    朴素贝叶斯分类器的应用
    Win32环境下代码注入与API钩子的实现(转)
  • 原文地址:https://www.cnblogs.com/lochan/p/3857525.html
Copyright © 2011-2022 走看看