倍增Floyd的时候在维护当前数位权值p的时候同时维护一个前缀和pA,即如果p表示路径长度为i的路径的方案数,那么pA表示路径长度为1~i的路径的方案数的和。每次翻倍的时候pA=pA*p+pA;p=p*p。可以用pA和p更新快速幂的答案。时间复杂度O(n^3 log k)。
#include<bits/stdc++.h>
#define N 105
using namespace std;
char s[N][N];
int n,k,mod;
long long ans;
struct Matrix{
long long a[N][N];
Matrix(){memset(a,0,sizeof a);}
}base;
Matrix operator* (Matrix a,Matrix b){
Matrix c;
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
return c;
}
Matrix operator+ (Matrix a,Matrix b){
Matrix c;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
c.a[i][j]=(a.a[i][j]+b.a[i][j])%mod;
return c;
}
Matrix ksm(int n){
Matrix re=base,p=base,pA=base;
--n;
while(n){
if(n&1) re=re*p+pA;
pA=pA*p+pA;
p=p*p;
n>>=1;
}
return re;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%s",s[i]+1);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(s[i][j]=='Y')base.a[i][j]=1;
else base.a[i][j]=0;
}
}
scanf("%d%d",&k,&mod);
if(k<3){
printf("0\n");
return 0;
}
Matrix an=ksm(k-1);
for(int i=1;i<=n;++i) ans=(ans+an.a[i][i])%mod;
printf("%lld\n",ans);
return 0;
}