2018.12.08【NOIP提高組】模擬B組 JZOJ 5223 B
阿新 • • 發佈:2018-12-13
描述
給定一個 的網格圖,一開始每個格子上都站著一個機器人。每一步機器人可以走到相鄰格子或留在原地,同一個格子上可以有多個機器人。問走 步後,有多少種走法,滿足每個格子上都有機器人。答案對 取模。
資料範圍:
思路
表示從第 格走到第 格的方案數,得到方程
然後我們矩陣乘法加速一下
最後全排列( )列舉一下機器人的最終落點,計算即可
時間複雜度:
拓展
若資料擴大成 的矩陣,則還需要另一個 ,時間複雜度:
程式碼
#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);//輸出
}
```