• 【JZOJ5223】B【矩阵乘法】【DFS】


    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/5223
    题目图片:
    http://wx4.sinaimg.cn/mw690/0060lm7Tly1fy2w5kn4jbj30in0gk74z.jpg
    给定一个3×33 imes3的网格图,一开始每个格子上都站着一个机器人。每一步机器人可以走到相邻格子或留在原地,同一个格子上可以有多个机器人。问走nn步后,有多少种走法,满足每个格子上都有机器人。答案对109+710^9+7取模。


    思路:

    n1018nleq 10^{18}告诉我们什么?
    log n?log n?显然不可做。
    n?sqrt{n}?显然过不了。
    3×33 imes 3的矩阵?矩阵乘法!

    f[i][j]f[i][j]表示走nn步从格子ii到格子jj的方案数。那么很明显,中间矩阵aa就是相邻格子为11,否则为00。然后枚举每一个起始格子,跑一边矩阵乘法。就可以得到任意两点走nn步的方案数。
    然后就DFSDFS每一个格子的机器人最终会走到哪一个格子。然后求ansans即可。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    
    const int MOD=1000000007;
    ll n,f[10][10],a[10][10],ans;
    bool used[10];
    const ll A[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}
    };
    
    void mul(int x)
    {
    	ll c[10];
    	memset(c,0,sizeof(c));
    	for (int i=1;i<=9;i++)
    		for (int j=1;j<=9;j++)
    			c[j]=(c[j]+(f[x][i]*a[i][j]))%MOD;
    	memcpy(f[x],c,sizeof(f[x]));
    }
    
    void mulself()
    {
    	ll c[10][10];
    	memset(c,0,sizeof(c));
    	for (int i=1;i<=9;i++)
    		for (int j=1;j<=9;j++)
    			for (int k=1;k<=9;k++)
    				c[i][j]=(c[i][j]+a[i][k]*a[k][j])%MOD;
    	memcpy(a,c,sizeof(a));
    }
    
    void ksm(ll m,int x)
    {
    	while (m)
    	{
    		if (m&1) mul(x);
    		mulself();
    		m>>=1;
    	}
    }
    
    void dfs(int x,ll s)
    {
    	if (x>9)
    	{
    		ans=(ans+s)%MOD;
    		return;
    	}
    	for (int i=1;i<=9;i++)
    		if (!used[i])
    		{
    			used[i]=1;
    			dfs(x+1,s*f[x][i]%MOD);
    			used[i]=0;
    		}
    }
    
    int main()
    {
    	cin>>n;
    	for (int i=1;i<=9;i++)
    	{
    		f[i][i]=1;
    		memcpy(a,A,sizeof(a));
    		ksm(n,i);
    	}
    	dfs(1,1);
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    sublime text3安装package control插件图文教程
    conda创建新环境
    常用的vscode插件安装
    数组合并组合
    内核软死锁
    Ubuntu分区格式化并挂载新增磁盘方法
    Linux如何列出svn一个文件夹下的所有文件
    C++ UTF-8和GBK相互转化
    Linux shell如何用正则表达式匹配分组数据
    如何对接jsoncpp?
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998436.html
Copyright © 2020-2023  润新知