首先,如果所有黑色格子都不与边界相邻,设有
个黑色格子,答案为
。
其次,如果两幅最开始的图任意拼再一起都联通,答案显然为
。
最后我们就剩下左右拼起来联通和上下拼起来联通两种情况。这两种类似,而且都比较好计算。
这里只讲左右拼起来联通的情况。
我们设
为
阶分形中联通块的数量,
为
阶分形中有多少个联通块满足,这种分形复制一份左右拼起来会和一个联通块连在一起。则显然满足
,
表示原图黑色格子的数量,
表示原图有多少对左右相邻的黑色。
,
是原图中第一列和最后一列拼起来会有多少个黑色格子连在一起。然后再矩阵快速幂优化dp一下就好了。
#include<bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
const int N=1005,mod=1000000007;
int n,m,t,k1,k2,c1,c2;
ll k;
char s[N][N];
bool flag1,flag2;
struct matrix{
int a[4][4];
matrix(){
memset(a,0,sizeof(a));
}
matrix operator * (const matrix &b){
matrix c;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(a[i][j]){
for(int k=0;k<4;k++){
c.a[i][k]=(c.a[i][k]+1LL*a[i][j]*b.a[j][k]%mod)%mod;
}
}
}
}
return c;
}
}a,b;
int fastpow(int a,ll x){
int res=1;
while(x){
if(x&1){
res=1LL*res*a%mod;
}
x>>=1;
a=1LL*a*a%mod;
}
return res;
}
matrix fastpow(matrix a,ll x){
matrix res=a;
x--;
while(x){
if(x&1){
res=res*a;
}
x>>=1;
a=a*a;
}
return res;
}
int main(){
scanf("%d%d%lld",&n,&m,&k);
if(k==1){
puts("1");
return 0;
}
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++){
if(s[i][j]=='#'){
t++;
if(s[i][j-1]=='#'){
k1++;
}
if(s[i-1][j]=='#'){
k2++;
}
}
}
}
for(int i=1;i<=n;i++){
if(s[i][1]=='#'&&s[i][m]=='#'){
c1++;
flag1=true;
}
}
for(int i=1;i<=m;i++){
if(s[1][i]=='#'&&s[n][i]=='#'){
c2++;
flag2=true;
}
}
if(!flag1&&!flag2){
printf("%d\n",fastpow(t,k-1));
}else if(flag1&&flag2){
puts("1");
}else if(flag1&&!flag2){
a.a[0][0]=1;
a.a[0][1]=1;
b.a[0][0]=t;
b.a[1][0]=mod-k1;
b.a[1][1]=c1;
a=a*fastpow(b,k-1);
printf("%d\n",a.a[0][0]);
}else{
a.a[0][0]=1;
a.a[0][1]=1;
b.a[0][0]=t;
b.a[1][0]=mod-k2;
b.a[1][1]=c2;
a=a*fastpow(b,k-1);
printf("%d\n",a.a[0][0]);
}
return 0;
}