[AGC003F] Fraction of Fractal(矩阵乘法)
Description
Snuke从他的母亲那里得到了生日礼物——一个网格。网格有H行W列。每个单元格都是黑色或白色。所有黑色单元格都是四联通的,也就是说,只做水平或垂直移动且只经过黑色单元格即可从任何黑色单元格移动到任何其他黑色单元格。
第i行第j列的单元格的颜色由字符si,j表示。如果si,j是 #,该单元格为黑色;如果si,j是 .,该单元格为白色。至少一个单元格是黑色的。
我们定义「分形」如下:0级分形是一个 1×1的黑色单元格.k级分形由H行W列较小一级的分形按照 Snuke 的网格的样式拼成:与Snuke 网格中的黑色单元格对应的位置是一个k级分形;与Snuke 网格中的白色单元格对应的位置是一个单元格全部为白色,尺寸与k级分形相同的网格。
您将得到 Snuke 的网格的描述和整数 K。请求出K级分形中黑色单元格组成的连通分量数,模1000000007。
Input
第一行三个整数H,W,K如题目描述
接下来H行,每行W个字符
Output
输出K级分形中黑色单元格组成的连通分量数,模1000000007。
题解:
一看 \(K=10^8\) 肯定是log级别的算法,一下想到矩阵快速幂。
首先,一个网格的上面和下面,左边和右边都连通,那么不管怎么分它都是连通的,所以答案是 \(1\)。
如果一个网格上面和下面,左边和右边都不连通,那么不管怎么分都是不连通的,所以答案是 \(x^{k-1}\),\(x\) 为黑块总个数。
剩下就是行连通,列不连通了。(不然转一下就好了)
x[k] 表示 k 级分型有多少个黑块。
y[k] 表示 k 级分型有多少个黑块满足这行的下一个也是黑块。
z[k] 表示 k 级分型有多少行是连通的。
手推可得:
\(x[k]=x[k-1]^2\)
\(y[k]=x[k-1]y[k-1]+z[k-1]y[k-1]\)
\(z[k]=z[k-1]^2\)
构造矩阵:
x & y \\
0 & z
\end{matrix}\right ] \]
求这个矩阵的 \(k-1\) 次方,答案为 \(x-y\)。
CODE:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mod 1000000007
int n,m;
char s[1005][1005],tmp[1005][1005];
long long k;
struct Matrix{
long long mat[5][5];
Matrix(){memset(mat,0,sizeof(mat));}
Matrix operator*(const Matrix &b)const{
Matrix c;
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++)
c.mat[i][j]+=mat[i][k]*b.mat[k][j];
c.mat[i][j]%=mod;
}
return c;
}
Matrix operator^(long long x)const{
Matrix a(*this),ans;
for(int i=1;i<=2;i++)ans.mat[i][i]=1;
while(x){
if(x&1)ans=ans*a;
x>>=1,a=a*a;
}
return ans;
}
}mat;
int qpow(int x,long long y){
int ans=1;
while(y){
if(y&1)ans=1LL*ans*x%mod;
y>>=1,x=1LL*x*x%mod;
}
return ans;
}
bool check(){
for(int i=1;i<=n;i++)
if(s[i][1]=='#'&&s[i][m]=='#')return true;
return false;
}
void turn(){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
tmp[m-j+1][i]=s[i][j];
swap(n,m);
memcpy(s,tmp,sizeof(s));
}
int main(){
scanf("%d%d%lld",&n,&m,&k);
int x=0,y=0,z=0;
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++)x+=s[i][j]=='#';
}
bool a=check(),b=(turn(),check());turn();
if(a&&b)return printf("1"),0;
else if(!a&&!b)return printf("%d",qpow(x,k-1)),0;
else if(b)turn();
for(int i=1;i<=n;i++)
z+=s[i][1]=='#'&&s[i][m]=='#';
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++)y+=s[i][j]=='#'&&s[i][j+1]=='#';
mat.mat[1][1]=x,mat.mat[1][2]=y,mat.mat[2][2]=z;
mat=mat^(k-1);
printf("%lld",(mat.mat[1][1]-mat.mat[1][2]+mod)%mod);
}
[AGC003F] Fraction of Fractal(矩阵乘法)的更多相关文章
- [AGC003F] Fraction of Fractal 矩阵快速幂
Description SnukeSnuke从他的母亲那里得到了生日礼物--一个网格.网格有HH行WW列.每个单元格都是黑色或白色.所有黑色单元格都是四联通的,也就是说,只做水平或垂直移动且只经过 ...
- @atcoder - AGC003F@ Fraction of Fractal
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 H*W 黑白格图,保证黑格四连通. 定义分形如下:0 ...
- [agc003F]Fraction of Fractal
Description 传送门 Solution 本篇博客思路来自大佬的博客(侵删). 我们定义如果网格的第一行和最后一行的第i列都为黑色,则它是一个上下界接口.左右界接口定义同上. 如果上下界接口和 ...
- *HDU2254 矩阵乘法
奥运 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...
- *HDU 1757 矩阵乘法
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- CH Round #30 摆花[矩阵乘法]
摆花 CH Round #30 - 清明欢乐赛 背景及描述 艺术馆门前将摆出许多花,一共有n个位置排成一排,每个位置可以摆花也可以不摆花.有些花如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看 ...
- POJ3070 Fibonacci[矩阵乘法]
Fibonacci Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13677 Accepted: 9697 Descri ...
- bzoj 2738 矩阵乘法
其实这题跟矩阵乘法没有任何卵关系,直接整体二分,用二维树状数组维护(刚刚学会>_<),复杂度好像有点爆炸(好像有十几亿不知道是不是算错了),但我们不能怂啊23333. #include&l ...
- 【BZOJ-2476】战场的数目 矩阵乘法 + 递推
2476: 战场的数目 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 58 Solved: 38[Submit][Status][Discuss] D ...
随机推荐
- node的webserver模板
const express = require('express'); const swig =require('swig'); const fs = require('fs'); //创建服务器 c ...
- advanced regression to predict housing prices
https://docs.google.com/presentation/d/e/2PACX-1vQGlXP6QZH0ATzXYwnrXinJcCn00fxCOoEczPAXU-n3hAPLUfMfi ...
- getchar输入多行字符,原格式输出(包含换行符)
#include<stdio.h> int main() { FILE fp; ]; ; char ch; while((ch=getchar())!=EOF){ str[k++]=ch; ...
- 精通SpringBoot--整合Redis实现缓存
今天我们来讲讲怎么在spring boot 中整合redis 实现对数据库查询结果的缓存.首先第一步要做的就是在pom.xml文件添加spring-boot-starter-data-redis.要整 ...
- python列表中的赋值与深浅拷贝
首先创建一个列表 a=[[1,2,3],4,5,6] 一.赋值 a=[[1,2,3],4,5,6]b=aa[0][1]='tom'print(a)print(b)结果: [[1, 'tom', 3], ...
- BFS:HDU3085-Nightmare Ⅱ(双向BFS)
Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- wcf第三方客户端与wcf服务之间调用入门
Wcf服务与我们的客户端如何建立联系的呢.本文简单记录一下 1.创建我们的wcf服务程序. 第一个wcf服务库是创建我们的wcf库,运行时会单独来托管我们的程序,而非托管在iis下. 第二个wcf服务 ...
- Git-起步
Git命令行 只要输入git,Git就会不带任何参数地列出它的选项和最常用的子命令. 要得到一个完整的git子命令列表,可以输入git help --all 显示版本号 git --version 每 ...
- 菜鸟学Linux - Linux文件属性
在Linux中,文件的属性是一个很重要的概念,用户或者用户组对一个文件所拥有的权限,都可以从文件的属性得知. 我们可以通过ls -al命令,列出某个文件夹下面的所有文件(包括以.开头的隐藏文件).下面 ...
- BZOJ 3420: Poi2013 Triumphal arch
二分答案 第二个人不会走回头路 那么F[i]表示在i的子树内(不包括i)所需要的额外步数 F[1]==0表示mid可行 k可能为0 #include<cstdio> #include< ...