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. 国密算法--Openssl 实现国密算法(加密和解密)

    上一次讲了产生密钥,这次我们讲一下加密解密的实现. 先说一下加密解密的流程,一下这些内容都是从国密局发布的国密标准文档里面摘录出来的.大家可以去国密局的网站上自己下载. 下列符号适用于本部分. A,B ...

  2. [文章存档]Azure .net WebAPP的js/css文件过大导致访问慢的解决办法

    https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-qa-j ...

  3. Linux系列——安装双系统Ubuntu

    作为一个穷人,电脑破得不行却没钱换,怎么办呢,不如换个Ubuntu吧,没有Windows那么多后台应用,在我这台古董上稍微流畅一点. Linux有很多发行版,比较流行和适合入门的就是Ubuntu和De ...

  4. kali linux执行apt-get update失败(数字签名过期)

    想要安装某个软件,执行apt-get update 失败,出现下面的错误: 自己查看了更新源是没有问题的,根据提示的错误google了一下,发现是数字签名过期了. 执行下面命令: apt-key ad ...

  5. java并发编程原理

    一.java内存模型 Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样底层细节.此处的变量与Java编程时所说的变量不一样,指包括了实例字段 ...

  6. (转)一个简单的rest_framework demo

    转发:https://www.cnblogs.com/fu-yong/p/9100559.html models.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from ...

  7. IOS上z-index和fixed定位无效

    IOS上z-index和fixed定位无效 在该元素上加: -webkit-transform:translateZ(1px); -moz-transform:translateZ(1px); -o- ...

  8. 成功安装Python-myqldb

    试过很多其他的都不行 http://www.centoscn.com/CentosBug/softbug/2017/0424/8737.html

  9. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128)的解决

    在用爬虫爬取网络小说的时候出现该问题. 估计是字符格式转换格式的错误. 暂时无法解决,搜索了其他博主的解决方案. 以下两个方案靠谱: <一>适用于全篇 import sys default ...

  10. 王者荣耀交流协会final发布文案美工展示博客

    logo: 我们的logo是蓝底白字,非常简洁大气的设计感,上面印有我们的软件名称,更好的直观的彰显了我们的主题.我们的软件就是要迎合使用者,给使用者更加方便快捷的工作体验,更好的衡量自己的时间分配. ...