版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/84894326
描述
给定一个 的网格图,一开始每个格子上都站着一个机器人。每一步机器人可以走到相邻格子或留在原地,同一个格子上可以有多个机器人。问走 步后,有多少种走法,满足每个格子上都有机器人。答案对 取模。
数据范围:
思路
表示从第 格走到第 格的方案数,得到方程
然后我们矩阵乘法加速一下
最后全排列( )枚举一下机器人的最终落点,计算即可
时间复杂度:
拓展
若数据扩大成 的矩阵,则还需要另一个 ,时间复杂度:
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define WYC 1000000007
using namespace std;
typedef long long LL;
LL n,s,f[9][9];
int b[10]={0,1,2,3,4,5,6,7,8,9};
struct node{LL a[9][9];}x,ans;
bool vis[9];
inline LL ksc(LL a,LL b)//快速乘
{
a%=WYC;b%=WYC;
long long c=(long double)a*b/WYC;
long long ans=a*b-c*WYC;
if(ans<0) ans+=WYC;
else if(ans>=WYC) ans-=WYC;
return ans;
}
inline node mul(node x,node y)//矩阵乘法
{
node c;
memset(&c,0,sizeof(c));
for(register int k=0;k<9;k++)
for(register int i=0;i<9;i++)
for(register int j=0;j<9;j++)
(c.a[i][j]+=ksc(x.a[i][k],y.a[k][j]))%=WYC;
return c;
}
inline void ksm(LL y)//矩阵乘法+预处理
{
memset(&ans,0,sizeof(ans));
memset(&x,0,sizeof(x));
for(register int i=0;i<9;i++) ans.a[i][i]=1;
x.a[0][0]=x.a[0][1]=x.a[0][3]=1;
x.a[1][0]=x.a[1][1]=x.a[1][2]=x.a[1][4]=1;
x.a[2][1]=x.a[2][2]=x.a[2][5]=1;
x.a[3][0]=x.a[3][3]=x.a[3][4]=x.a[3][6]=1;
x.a[4][1]=x.a[4][3]=x.a[4][4]=x.a[4][5]=x.a[4][7]=1;
x.a[5][2]=x.a[5][4]=x.a[5][8]=x.a[5][5]=1;
x.a[6][3]=x.a[6][7]=x.a[6][6]=1;
x.a[7][4]=x.a[7][6]=x.a[7][7]=x.a[7][8]=1;
x.a[8][5]=x.a[8][7]=x.a[8][8]=1;
for(;y;x=mul(x,x),y>>=1)if(y&1)ans=mul(ans,x);
return;
}
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
signed main()
{
n=read();
ksm(n);//矩阵乘法快速幂
memcpy(f,ans.a,sizeof(ans.a));
do
{
LL now=1;
for(register int i=0;i<9;i++) (now*=f[i][b[i]])%=WYC;
(s+=now)%=WYC;
}while(next_permutation(b,b+9));//枚举全排列
write(s);//输出
}
```