[矩阵快速幂] Atcoder AGC003 F. Fraction of Fractal
2017-12-07 20:48
211 查看
很神的题!!!
首先观察一下每次转移
如果初始的图案存在某一行 i,满足行的两个端点为黑,且存在某一列也是满足这样的条件,那么答案就是1,因为原来就连通的黑块转移后的图案也是联通的。
如果行和列都不满足,因为每次转移答案都会乘 x, 那么答案就是 xk−1 ,其中 x 为初始图案中的黑块数量。
如果只有行满足这样的条件(列满足的话转一下图案),
设 x 等于黑块的数量, y 等于初始图像中 ai,j 和 ai,j+1 都为黑的 (i,j) 数量, z 为几行满足上面的条件
那么每次转移就有
x′=x2
y′=xy+yz
z′=z2
这个东西退一下可以知道…
用矩阵转移就好了…
首先观察一下每次转移
如果初始的图案存在某一行 i,满足行的两个端点为黑,且存在某一列也是满足这样的条件,那么答案就是1,因为原来就连通的黑块转移后的图案也是联通的。
如果行和列都不满足,因为每次转移答案都会乘 x, 那么答案就是 xk−1 ,其中 x 为初始图案中的黑块数量。
如果只有行满足这样的条件(列满足的话转一下图案),
设 x 等于黑块的数量, y 等于初始图像中 ai,j 和 ai,j+1 都为黑的 (i,j) 数量, z 为几行满足上面的条件
那么每次转移就有
x′=x2
y′=xy+yz
z′=z2
这个东西退一下可以知道…
用矩阵转移就好了…
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <assert.h> using namespace std; typedef long long ll; const int N=1010,P=1e9+7; struct mat{ int a[2][2]; mat(){ a[0][0]=a[1][1]=a[0][1]=a[1][0]=0; } int *operator [](int x){ return a[x]; } friend mat operator *(mat a,mat b){ mat c; c[0][0]=(1LL*a[0][0]*b[0][0]+1LL*a[0][1]*b[1][0])%P; c[0][1]=(1LL*a[0][0]*b[0][1]+1LL*a[0][1]*b[1][1])%P; c[1][0]=(1LL*a[1][0]*b[0][0]+1LL*a[1][1]*b[1][0])%P; c[1][1]=(1LL*a[1][0]*b[0][1]+1LL*a[1][1]*b[1][1])%P; return c; } }; mat u; int n,m; char a[N][N],b[N][N]; ll k; inline int judge(){ for(int i=1;i<=n;i++) if(a[i][1]=='#' && a[i][m]=='#') return 1; return 0; } inline void turn(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) b[m-j+1][i]=a[i][j]; swap(n,m); memcpy(a,b,sizeof(a)); } inline int Pow(int x,ll y){ int ret=1; for(;y;y>>=1,x=1LL*x*x%P) if(y&1) ret=1LL*ret*x%P; return ret; } inline mat Pow(mat x,ll y){ mat ret=u; for(;y;y>>=1,x=x*x) if(y&1) ret=ret*x; return ret; } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); u[0][0]=u[1][1]=1; scanf("%d%d%lld",&n,&m,&k); int cnt=0; for(int i=1;i<=n;i++){ scanf("%s",a[i]+1); for(int j=1;j<=m;j++) cnt+=a[i][j]=='#'; } int A=judge(),B=(turn(),judge()); turn(); if((A && B) || !k) return puts("1"),0; if(!A && !B) return printf("%d\n",Pow(cnt,k-1)),0; if(!A) turn(); int c=0,b=0; for(int i=1;i<=n;i++) c+=(a[i][1]=='#' && a[i][m]=='#'); for(int i=1;i<=n;i++) for(int j=1;j<m;j++) b+=(a[i][j]=='#' && a[i][j+1]=='#'); mat w,ans; w[0][0]=cnt; w[0][1]=b; w[1][1]=c; ans=Pow(w,k-1); printf("%d\n",(ans[0][0]+P-ans[0][1])%P); return 0; }
相关文章推荐
- uva 11149 - Power of Matrix 【倍增 + 矩阵快速幂】
- 【矩阵幂的和+矩阵快速幂】Power of Matrix UVA - 11149
- HDU 3306 Another kind of Fibonacci(快速幂矩阵)
- HDU 4686 Arc of Dream(快速幂矩阵)
- HDU 5318——The Goddess Of The Moon——————【矩阵快速幂】
- [HDU 3306] Another kind of Fibonacci · 矩阵快速幂
- hdu 4686 Arc of Dream_矩阵快速幂
- 7_22_E题 Power of Matrix(矩阵快速幂+倍增)
- 2016弱校联盟十一专场10.5 F Fibonacci of Fibonacci(矩阵快速幂 + 循环节)
- UVA 11149(B)——Power of Matrix (矩阵快速幂,倍增法)
- hdu 4686 Arc of Dream_矩阵快速幂
- HDU 5318 The Goddess Of The Moon(矩阵快速幂)
- HDU 4686 Arc of Dream (矩阵快速幂)
- CSU 1658 IQ of XUEXX’s descendants 矩阵快速幂
- UVa 11149 Power of Matrix (矩阵快速幂,倍增法或构造矩阵)
- hdoj 4686 Arc of Dream 【矩阵快速幂】
- HDU 4686 Arc of Dream(矩阵快速幂)
- hdu 4686 Arc of Dream【矩阵快速幂】
- hdu 4686 Arc of Dream(矩阵快速幂)
- HDU 4686 Arc of Dream(矩阵快速幂)