• 11.02B


    题目描述

    9 个机器人,在 3 * 3 的方格里,一开始 9 个机器人分别站在 9 个格子上,每一步机器人可
    以往临近的一个格子移动或留在原地(同一个格子可以有多个机器人停留),经过 n 步后有
    多少种不同的走法,使得每个格子上都有 1 机器人停留。由于方法数量巨大,输出 Mod
    10^9 + 7 的结果。

    输入输出格式

    输入格式

    第一行包含一个整数 n。

    输出格式

    输出一行输出走法的数量 Mod 10^9 + 7

    数据范围

    对于 40%的数据,1 <= n<= 10;
    对于 70%的数据,1 <= n <= 10^6;
    对于 100%的数据,1 <= n <= 10^18。

    样例

    样例一输入:

    1
    

    样例一输出:

    299
    

    思路

    1.40%数据

    暴力
    期望复杂度 $ Theta left( 玄学 ight) $

    2.70%数据

    考虑dp
    dp[i][j][k] 表示走了i步,起点在j终点在k的方案数
    dfs枚举全排列
    期望复杂度 $ Theta left( 81n ight) $

    3.100%数据

    考虑优化dp转移
    很明显一个点朝其他点转移的状态量小且固定
    利用矩阵快速幂优化掉n
    期望复杂度 $ Theta left( 9^{3} log n ight) $

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <list>
    #include <map>
     
    #define ll long long
    #define ull unsigned long long
    
    using namespace std;
    const int mod = 1e9+7;
    int dp[10][10];
    bool mp[10];
    ll n,ans;
    ll e[10][10] = {
        {0,0,0,0,0,0,0,0,0,0},
        {0,1,1,0,1,0,0,0,0,0},
        {0,1,1,1,0,1,0,0,0,0},
        {0,0,1,1,0,0,1,0,0,0},
        {0,1,0,0,1,1,0,1,0,0},
        {0,0,1,0,1,1,1,0,1,0},
        {0,0,0,1,0,1,1,0,0,1},
        {0,0,0,0,1,0,0,1,1,0},
        {0,0,0,0,0,1,0,1,1,1},
        {0,0,0,0,0,0,1,0,1,1},
    };
    
    struct mat {
        ll p[10][10];
        mat(){memset(p,0,sizeof(p));}
        void cl() { for(int i=1;i<=9;i++) p[i][i]=1;}
        mat operator * (const mat&a)const {
            mat tmp;
            for(int k = 1; k <= 9; k++)
                for(int i = 1; i <= 9; i++)
                    for(int j = 1; j <= 9; j++) {
                        tmp.p[i][j] += p[i][k] * a.p[k][j];
                        if(tmp.p[i][j] >= mod) tmp.p[i][j] %= mod;
                    }
            return tmp;
        }
    }XJH;
    
    inline void Init() {
        memcpy(XJH.p,e,sizeof e);
    }
    
    mat ksm(mat bs,ll x) {
        mat ans;
        ans.cl();
        while(x) {
            if(x & 1) ans = ans * bs;
            bs = bs * bs;
            x >>= 1;
        }
        return ans;
    }
    
    void dfs(int step,ll sum) {
        if(step == 10) {
            ans += sum;
            if(ans >= mod) ans %= mod;
            return;
        }
        for(int i = 1; i <= 9; i++)
            if(!mp[i]) {
                mp[i] = 1;
                dfs(step+1,(sum * dp[i][step])%mod);
                mp[i] = 0;
            }
    }
    
    int main() {
        // freopen("B.in","r",stdin);
        // freopen("B.out","w",stdout);
        Init();
        scanf("%lld",&n);
        mat bs = ksm(XJH,n);
    /*
        for(int i = 0; i <= 9; i++)
            for(int j = 0; j <= 9; j++)
                if(j == 9) cout << bs.p[i][j] << endl;
                else cout << bs.p[i][j] << ' ' ;
    */
        for(int i = 1; i <= 9; i++) {
            mat tmp;
            tmp.p[1][i] = 1;
            tmp = tmp*bs;
            for(int j = 1; j <= 9; j++)
                dp[i][j] = tmp.p[1][j];
        }
        dfs(1,1);
        printf("%lld",ans);
    }
    
  • 相关阅读:
    I2S波形解析
    F407整点原子I2C波形解码
    WAVE格式文件说明
    ADC结构体初始化成员
    这次,我是真的想吐槽MDK
    I2S源程序(正点原子F407探索者)
    强制类型转换
    嵌套结构体的初始化
    lua 元方法 __index
    lua pairs 与 ipairs
  • 原文地址:https://www.cnblogs.com/ullio/p/9899173.html
Copyright © 2020-2023  润新知