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优化方向——优化Unity游戏中的图形渲染(译)

    CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...

  2. 信息提示 - bootStrap4常用CSS笔记

    .alert 基类 .alert-{success.info.warning.danger.primary.secondary.light.dark} 各种类型的配色样式 .fade..show 设置 ...

  3. jsp内置对象 转发与重定向的区别

    jsp 内置对象  转发与重定向的比较 重定向和转发有一个重要的不同:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程. 与之相反,重 ...

  4. dom学习要点

    Dom操作 1.文本内容操作 - innerText:操作文本 - innerHtml:操作全内容 //innerText标签: <div id='i2' ><a>土味程序员& ...

  5. Python-RabbitMQ(持久化)

    生产者: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import pika   connection = pika.BlockingConnection(pi ...

  6. [Windows][C#][.NET][WPF]基于ArcFace2.0+红外双目摄像头的活体检测

    废话不多说 直接上图这个是demo中用到的双目摄像头,一个是红外的,一个是正常的rgb摄像头两个usb接口,在电脑上呈现两路摄像头通道程序检测RGB输出图像,当检测到有人脸时,用RGB人脸的位置到红外 ...

  7. c++ 使用this指针进行串联的函数调用

    如代码所示,在每个成员函数函数体最后返回*this.即可实现串联调用. class Time { public: Time(, , ); Time &setHour(int); Time &a ...

  8. 第7讲:SQL Server简介

    SQL Server是微软公司提供的一款关系数据库管理系统. 操作数据库有两种方式:SQL语句和可视化的SSMS,该文章所有操作均基于SSMS. 一.SSMS(SQL Server Managemen ...

  9. Ambiguous mapping. Cannot map 'labelInfoController' method

    使用springboot项目中,启动时出现Ambiguous mapping. Cannot map 'labelInfoController' method , 原因是,@RequestMappin ...

  10. dazhewang数据库初设计

    mysql> use dazhe; Database changed mysql> create table shops(id int primary key auto_increment ...