Description

  

​   原题链接

  

​  

  

Solution

  

​   神题。

  

​   定义一个上边界或下边界的格子为”上下接口“,当且仅当上下边界该位置的格子都是黑色的。

  

​   ”左右接口“同理。

  

  首先特判掉\(k\)小于等于1的情况,答案都是1。

  

​   然后特判掉两种情况:上下接口和左右接口同时存在时,答案显然为1;二者皆不存在时,答案就是\(s^{k-1}\),其中\(s\)为给定网格的黑格子数目。

  

​   所以接下来我们考虑的问题是:\(k\ge 2\),且仅存在上下接口或左右接口。现在我们只考虑前者的情况,后者可以通过旋转原网格来达到同样的效果。

  

​   首先来观察2级分形的结构:我们不妨把其中的每一块1级分形看做一个节点,如果两个相邻1级分形可以互相连通,则视为将其对应节点之间连一条。由此我们对2级分形构造出一张图。

  

​   对于3级及其以上分形,节点的定义不再扩展,依然是1级分形、表示1级分形之间是否连通。

  

​   可以发现,由于当前只存在上下接口,因此2级分形的图是由若干条竖直方向的链构成的。推广一下,就会发现,对于\(k\)级分形\((k \ge 2)\)对应的图,它们都有着这个性质。

  

​   将链看成树,我们就可以运用森林的性质:树的个数等于总点数减去总边数。则连通块个数等于总点数减去总边数。

  

​   记\(a\)表示给定网格样式中,上下两个格子都是黑色的位置有多少,即\(\sum [map_{i,j}=map_{i+1,j}='\#']\)

  

​   记\(b\)表示上下接口的个数(同一列的两个接口只算1个)

  

​   记\(V_k\)表示\(k\)级分形图中的个数,\(E_k\)表示\(k\)级分形图中的条数。则有递推式:

  

    \(V_2=s\),\(E_2=a\)

    \(V_k=V_{k-1}*s\),\(E_k=E_{k-1}*s+ab^{k-2}\)

    

  其中\(V\)的递推显然,而\(E\)的含义则是:每个低级分形中边个数乘上扩增倍数,加上低级分形在组合成高级分形时通过上下接口新产生的边数。注意\(b\)之所以含有一个幂形式,是因为随着分形级数的不断扩增,上下接口的数量也在不断增长。

  

  使用矩阵快速幂计算就做完了。

  

  

  

Code

  

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=1005;
const int MOD=1e9+7;
int n,m,blacksum;
ll kk;
char str[N][N];
int map[N][N];
int hcnt,vcnt,lh,lv;
inline void plus(int &x,int y){
x=(x+y>=MOD)?(x+y-MOD):x+y;
}
inline void swap(int &x,int &y){
x^=y^=x^=y;
}
inline int fmi(int x,ll y){
int res=1;
for(;y;x=1LL*x*x%MOD,y>>=1)
if(y&1)
res=1LL*res*x%MOD;
return res;
}
struct Mat{/*{{{*/
int n,m;
int a[4][4];
Mat(){
memset(a,0,sizeof a);
}
Mat(int _n,int _m){
n=_n; m=_m;
clear();
}
void setUnit(){
if(n!=m) return;
for(int i=1;i<=n;i++)
a[i][i]=1;
}
void clear(){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=0;
}
friend Mat operator * (Mat u,Mat v){
Mat res=Mat(u.n,v.m);
for(int i=1;i<=u.n;i++)
for(int j=1;j<=v.m;j++)
for(int k=1;k<=u.m;k++)
//(res.a[i][j]+=1LL*u.a[i][k]*v.a[k][j]%MOD)%=MOD;
plus(res.a[i][j],1LL*u.a[i][k]*v.a[k][j]%MOD);
return res;
}
}O,T;/*}}}*/
void readData(){
scanf("%d%d%lld",&n,&m,&kk);
for(int i=1;i<=n;i++){
scanf("%s",str[i]+1);
for(int j=1;j<=m;j++)
blacksum+=(str[i][j]=='#');
}
}
int getTypeAndInit(){
for(int i=1;i<=n;i++)
hcnt+=(str[i][1]=='#'&&str[i][m]=='#');
for(int j=1;j<=m;j++)
vcnt+=(str[1][j]=='#'&&str[n][j]=='#');
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(j<m)
lh+=(str[i][j]=='#'&&str[i][j+1]=='#');
if(i<n)
lv+=(str[i][j]=='#'&&str[i+1][j]=='#');
}
if(hcnt&&vcnt) return 1;
else if(!hcnt&&!vcnt) return 2;
if(hcnt){
swap(hcnt,vcnt);
swap(lh,lv);
}
return 3;
}
void fillMatrix(){
O=Mat(1,3);
O.a[1][1]=blacksum; O.a[1][2]=lv; O.a[1][3]=vcnt;
T=Mat(3,3);
T.a[1][1]=blacksum;
T.a[2][2]=blacksum; T.a[3][2]=lv;
T.a[3][3]=vcnt;
}
Mat mat_fmi(Mat x,ll y){
Mat res=Mat(x.n,x.n);
res.setUnit();
for(;y;x=x*x,y>>=1)
if(y&1)
res=res*x;
return res;
}
void solve(){
fillMatrix();
T=mat_fmi(T,kk-2);
O=O*T;
int ans=O.a[1][1]-O.a[1][2];
printf("%d\n",ans<0?ans+MOD:ans);
}
int main(){
readData();
if(kk<=1){
puts("1");
return 0;
}
int type=getTypeAndInit();
if(type==1)//whole
puts("1");
else if(type==2)//isolated
printf("%d\n",kk==0?1:fmi(blacksum,kk-1));
else
solve();
return 0;
}

【AGC003F】Fraction of Fractal的更多相关文章

  1. 【leetcode】Fraction to Recurring Decimal

    Fraction to Recurring Decimal Given two integers representing the numerator and denominator of a fra ...

  2. 【LeetCode】数学(共106题)

    [2]Add Two Numbers (2018年12月23日,review) 链表的高精度加法. 题解:链表专题:https://www.cnblogs.com/zhangwanying/p/979 ...

  3. 【LeetCode】哈希表 hash_table(共88题)

    [1]Two Sum (2018年11月9日,k-sum专题,算法群衍生题) 给了一个数组 nums, 和一个 target 数字,要求返回一个下标的 pair, 使得这两个元素相加等于 target ...

  4. HDU 5912 Fraction 【模拟】 (2016中国大学生程序设计竞赛(长春))

    Fraction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  5. 【LeetCode】166. Fraction to Recurring Decimal 解题报告(Python)

    [LeetCode]166. Fraction to Recurring Decimal 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingz ...

  6. 【LeetCode】592. Fraction Addition and Subtraction 解题报告(Python)

    [LeetCode]592. Fraction Addition and Subtraction 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuem ...

  7. 【Codeforces Round #433 (Div. 2) A】Fraction

    [链接]h在这里写链接 [题意] 在这里写题意 [题解] 枚举分子从高到低就好. 这样得到的一定是最大的. (可以约分没错,但是约分过后和就不是n了,所以不会有错的) [错的次数] 0 [反思] 在这 ...

  8. 【BZOJ1672】[Usaco2005 Dec]Cleaning Shifts 清理牛棚 动态规划

    [BZOJ1672][Usaco2005 Dec]Cleaning Shifts Description Farmer John's cows, pampered since birth, have ...

  9. 【MySQL】TokuDB引擎初探(MySQL升级为Percona,MySQL升级为MariaDB)

    参考:http://blog.sina.com.cn/s/blog_4673e6030102v46l.html 参考:http://hcymysql.blog.51cto.com/5223301/14 ...

随机推荐

  1. Unity中使用C#实现UDP广播

    没有系统的学习过网络,想做联机游戏还真是费劲,想做在局域网内实现自动搜索服务器的功能,然后就想到了使用UDP进行广播,把服务器的信息广播给每一个玩家. Socket udpSocket = new S ...

  2. 互联网校招面试必备——Java多线程

    本文首发于我的个人博客:尾尾部落 本文是我刷了几十篇一线互联网校招java后端开发岗位的面经后总结的多线程相关题目,虽然有点小长,但是面试前看一看,相信能帮你轻松啃下多线程这块大骨头. 什么是进程,什 ...

  3. Axure 制作 轮播 左右按钮轮播图

    1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ...

  4. python打包成exe文件

    在cmd命令提示符窗口中输入pip install pyinstaller(在python3的环境下,假如不能安装的话,用pip3 install pyinstaller指令) 使用指令pyinsta ...

  5. 51nod-1298 圆与三角形(计算几何超详解)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1298 给出圆的圆心和半径,以及三角形的三个顶点,问圆同三角形是 ...

  6. Python列表解析

    列表解析 根据已有列表,高效创建新列表的方式. 列表解析是Python迭代机制的一种应用,它常用于实现创建新的列表,因此用在[]中. 语法: [expression for iter_val in i ...

  7. win10浏览器访问vmware中ubuntu开启的某个服务端口出现的问题

    问题描述 1. win10系统中浏览器能正常访问  ubuntu中nginx服务器的80端口, 但是不能访问8082 问题原因 ubuntu 防火墙默认没有启用 8082端口, 需要开启这个端口号 解 ...

  8. sublime编写markdownm

    sublime编写markdownm 以前用有道云笔记,找了半天更改字体大小,结果还找不 到,那个字实在是太小了,像我这种有强迫症的患者,实 在受不了简约风格的有道云,所以上网找了与和诺插件并 受到一 ...

  9. java判断字符串编码

    是 public static String getEncoding(String str){ String encoding = "UTF-8"; try { if (str.e ...

  10. Daily Scrum (2015/10/29)

    今天晚上我们学霸项目的三个小组在一起开会,讨论如何能在后期使我们三个项目更好地结合在一起.为了三个小组的能够同时工作,不出现某一小组因需要其他小组成果而停滞的情况,我们决定围绕lucene,solr, ...