Atcoder Grand Contest 003 F - Fraction of Fractal(矩阵乘法)
Yet another AGC F,然鹅这次就没能自己想出来了……
首先需注意到题目中有一个条件叫做“黑格子组成的连通块是四联通的”,这意味着我们将所有黑格都替换为题目中 \(H\times W\) 的标准型之后,黑格(标准型)内部是不会对连通块个数产生贡献的,产生贡献的只可能是黑格与黑格之间的边不产生连通块。如果我们记 \(G_{\text{h}}\) 两个标准型横着拼在一起得到的 \(H\times 2W\) 的图形,\(G_{\text{v}}\) 为两个标准型竖着拼在一起得到的 \(2H\times W\) 的图形,那么稍微分析一下即可得到以下性质:
- 如果 \(G_{\text{h}},G_{\text{v}}\) 中都只有一个连通块,那么最终得到的 \(k\) 级分形也只有一个连通块。因为对于原来的标准型中的相邻两个黑格,由于 \(G_{\text{h}},G_{\text{v}}\) 连通,所以将这两个黑格分别替换为标准型后,这两个黑格所表示的连通块依旧连通,又因为这个标准型本来就是连通图,所以进行一次迭代(将黑格替换为标准型)后,该图中所有黑格表示的标准型都是连通的,也就是说该标准型的二级分形为连通图。又 \(\because G_{\text{h}}\) 连通,仿照上述推理过程可知 \(G_{\text{h}}\) 进行一次迭代后之后,所得的分形仍是连通图,即将该标准型的二级分形左右拼接后,可以得到连通形,\(G_{\text{v}}\) 也同理,如此归纳下去即可证明。
- 如果 \(G_{\text{h}},G_{\text{v}}\) 中都有两个连通块,那么最终得到的 \(k\) 级分形中有 \(\text{标准型中黑格个数}^{k-1}\) 个黑格,这个好办,\(G_{\text{h}},G_{\text{v}}\) 都有两个连通块,这意味着对于标准型中的任意两个相连的黑格,将它们分别替换为标准型后,彼此之间互不连通,也就是每个黑格各自成一个连通块,记原来的标准型中黑格个数为 \(C\),那么根据之前的推论,二级分形中有 \(C\) 个连通块,\(C^2\) 个黑格,三级分形中有 \(C^2\) 个连通块,\(C^3\) 个黑格,以此类推。
比较棘手的是 \(G_{\text{h}},G_{\text{v}}\) 刚好一个连通,一个不连通的情况。不妨设 \(G_{\text{h}}\) 连通,\(G_{\text{v}}\) 不连通。我们考虑探究一次迭代会对连通块个数产生什么影响。我们考虑使用一个并查集的思想,不妨假设所有黑格替换为的分形都单独成一个连通块,然后将能并的并起来,显然两个黑格表示的连通块能够并起来当且仅当它们左右相邻,而显然左右相邻的格子不会组成环,也就是说每次合并都是合法的,这样减少的连通块个数就是左右相邻的黑格个数,故一次迭代之后连通块的个数,就等于黑格个数减去左右相邻的黑格个数。
考虑怎样计算这个东西,设 \(a_k\) 为 \(k\) 级分形中左右相邻的黑格个数,\(b_k\) 为 \(k\) 级分形中的黑格个数,那么显然可以推出 \(b\) 的递推式 \(b_{k+1}=b_kb_1\),但是推出 \(a\) 的递推式还有些困难。考虑将 \(k\) 级分形替换为 \(k+1\) 级分形后,左右相邻的黑格的来头,显然它可能是一个黑格替换为一个标准型分形后,内部出现左右相邻的黑格,这部分我们是可以计算的,为 \(b_ka_1\),也有可能是本身左右相邻的黑格替换为标准型后,边界上出现左右相邻的黑格,我们发现这东西无法直接表示,那就设一下呗。再设 \(c_k\) 为 \(k\) 级分形中左右拼接的边界上左右相邻的黑格个数,设完之后这东西就很好表示了,为 \(a_kc_1\),即 \(a_{k+1}=b_ka_1+a_kc_1\)。最后考虑 \(c\) 的递推式,显然边界上相邻只可能是原来边界上相邻的黑格被替换为标准型后,每对相邻的黑格新多出 \(c_1\) 对出来,即 \(c_{k+1}=c_kc_1\)。
最后看下数据范围……\(10^{18}\),还有这么多递推式,那显然矩阵快速幂咯。稍微推推即可得到 \(\begin{bmatrix}b_k&a_k\\0&c_k\end{bmatrix}\times\begin{bmatrix}b_1&a_1\\0&c_1\end{bmatrix}=\begin{bmatrix}b_{k+1}&a_{k+1}\\0&c_{k+1}\end{bmatrix}\),即 \(\begin{bmatrix}b_k&a_k\\0&c_k\end{bmatrix}=\begin{bmatrix}b_1&a_1\\0&c_1\end{bmatrix}^k\),快速幂即可。
const int MAXN=1e3;
const int MOD=1e9+7;
int n,m;ll k;
char s[MAXN+5][MAXN+5];
int qpow(int x,ll e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
struct mat{
ll a[2][2];
mat(){memset(a,0,sizeof(a));}
mat operator *(const mat &rhs){
mat ret;
for(int i=0;i<2;i++) for(int j=0;j<2;j++)
for(int k=0;k<2;k++) ret.a[i][j]+=a[i][k]*rhs.a[k][j];
for(int i=0;i<2;i++) for(int j=0;j<2;j++) ret.a[i][j]%=MOD;
return ret;
}
};
int main(){
scanf("%d%d%lld",&n,&m,&k);if(!k) return puts("1"),0;
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
int ud_bor=0,lr_bor=0,ud_ins=0,lr_ins=0,cnt=0;
for(int i=1;i<=m;i++) ud_bor+=(s[1][i]=='#'&&s[n][i]=='#');
for(int i=1;i<=n;i++) lr_bor+=(s[i][1]=='#'&&s[i][m]=='#');
for(int i=1;i<n;i++) for(int j=1;j<=m;j++) ud_ins+=(s[i][j]=='#'&&s[i+1][j]=='#');
for(int i=1;i<=n;i++) for(int j=1;j<m;j++) lr_ins+=(s[i][j]=='#'&&s[i][j+1]=='#');
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cnt+=(s[i][j]=='#');
// printf("%d %d %d %d %d\n",ud_bor,lr_bor,ud_ins,lr_ins,cnt);
if(!ud_bor&&!lr_bor) printf("%d\n",qpow(cnt,k-1));
else if(ud_bor&&lr_bor) printf("1\n");
else{
mat trs,res;res.a[0][0]=res.a[1][1]=1;--k;
if(ud_bor) trs.a[0][0]=cnt,trs.a[0][1]=ud_ins,trs.a[1][1]=ud_bor;
else trs.a[0][0]=cnt,trs.a[0][1]=lr_ins,trs.a[1][1]=lr_bor;
for(;k;k>>=1,trs=trs*trs) if(k&1) res=res*trs;
printf("%d\n",(res.a[0][0]-res.a[0][1]+MOD)%MOD);
}
return 0;
}
Atcoder Grand Contest 003 F - Fraction of Fractal(矩阵乘法)的更多相关文章
- AtCoder Grand Contest 003 F - Fraction of Fractal
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_f 题目大意: 给定一个\(H×W\)的黑白网格,保证黑格四连通且至少有一个黑格 定义分形如下 ...
- AtCoder Grand Contest 003
AtCoder Grand Contest 003 A - Wanna go back home 翻译 告诉你一个人每天向哪个方向走,你可以自定义他每天走的距离,问它能否在最后一天结束之后回到起点. ...
- AtCoder Grand Contest 002 F:Leftmost Ball
题目传送门:https://agc002.contest.atcoder.jp/tasks/agc002_f 题目翻译 你有\(n*k\)个球,这些球一共有\(n\)种颜色,每种颜色有\(k\)个,然 ...
- AtCoder Grand Contest 003 D - Anticube
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_d 题目大意: 给定\(n\)个数\(s_i\),要求从中选出尽可能多的数,满足任意两个数之积 ...
- AtCoder Grand Contest 017 F - Zigzag
题目传送门:https://agc017.contest.atcoder.jp/tasks/agc017_f 题目大意: 找出\(m\)个长度为\(n\)的二进制数,定义两个二进制数的大小关系如下:若 ...
- AtCoder Grand Contest 003 E - Sequential operations on Sequence
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_e 题目大意 一串数,初始为\(1\sim N\),现有\(Q\)个操作,每次操作会把数组长度 ...
- AtCoder Grand Contest 011 F - Train Service Planning
题目传送门:https://agc011.contest.atcoder.jp/tasks/agc011_f 题目大意: 现有一条铁路,铁路分为\(1\sim n\)个区间和\(0\sim n\)个站 ...
- AtCoder Grand Contest 010 F - Tree Game
题目传送门:https://agc010.contest.atcoder.jp/tasks/agc010_f 题目大意: 给定一棵树,每个节点上有\(a_i\)个石子,某个节点上有一个棋子,两人轮流操 ...
- AtCoder Grand Contest 016 F - Games on DAG
题目传送门:https://agc016.contest.atcoder.jp/tasks/agc016_f 题目大意: 给定一个\(N\)点\(M\)边的DAG,\(x_i\)有边连向\(y_i\) ...
随机推荐
- python中的信号通信 blinker
信号: 信号是一种通知或者说通信的方式,信号分为发送方和接收方.发送方发送一中信号,接收方收到信号的进程会跳入信号处理函数,执行完后再跳回原来的位置继续执行.常见的linux中的信号,通过键盘输入Ct ...
- String直接赋字符串和new String的区别
String A="ABC"; String B=new String("ABC"); String A = "ABC";内存会去查找常量池 ...
- Unity 制作不规则形状button
在游戏开发中,我们有时需要制作不规则形状的按键. Unity3d中使用UGUI的Button控件只能实现规则的长方形按钮.而通过给Button的Image组件添加对应的贴图(sprite)我们可以实现 ...
- hdu 5178 pairs(BC第一题,,方法不止一种,,我用lower_bound那种。。。)
题意: X坐标上有n个数.JOHN想知道有多少对数满足:x[a]-x[b]<=k(题意给)[a<b] 思路: 额,,,直接看代码吧,,,, 代码: int T,n,k; int x[100 ...
- Vue3学习(十)之 页面、菜单、路由的使用
一.前言 好几天没更文了,周末真的太冷了,在家躺了一天不爱动.今天给暖气了,相对不那么冷了,就可以继续更文了. 由文章标题不难看出,就是实现点击菜单跳转的意思,我写的很直白了,哈哈. 二.实现点击菜单 ...
- docker 使用报错的相关问题
docker 创建本地主机实例Virtualbox 驱动报错,显示没有下载这个驱动 解决方案,下载virtuabox. https://www.cnblogs.com/effortday/p/1502 ...
- github上传和删除文件(三)
上传文件: git init git add * git commit -m "description" //git remote rm origin 或查看当前 git remo ...
- 攻防世界 WEB 高手进阶区 easytornado Writeup
攻防世界 WEB 高手进阶区 easytornado Writeup 题目介绍 题目考点 Python模板 tornado 模板注入 Writeup 进入题目, 目录遍历得到 /flag.txt /w ...
- Java测试开发--MySql之C3P0连接池(八)
连接池C3P0! 连接池技术的目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能 ! 下面以案例演示下C3P0的操作流程. 1.测试准备: ①MySql数据库一枚②database名为myte ...
- LeetCode 199. 二叉树的右视图 C++ 用时超100%
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...