【NOI2017模拟4.5】无限棋盘
2017-04-07 17:03
405 查看
题目
Description无聊的小A在一个无限大的棋盘上玩游戏,这个棋盘由一个M*N的模板不停重复生成。例如,当模板为:
honi
hsin
时,我们会生成如下棋盘:
…honihonihonihoni…
…hsinhsinhsinhsin…
…honihonihonihoni…
…hsinhsinhsinhsin…
其中,该棋盘在任意一个方向都可以无限延伸。
现在小A在棋盘上随机挑选一个位置,又随机挑选一个方向(八个方向之一),并从该位置开始,沿着挑选的方向走K-1步,沿路记下每一个经过的字母(包括起点),得到一个长度为K的字符串。他重复并独立地执行该操作两次,得到两个长度为K的字符串,他现在想知道,这两个字符串相同的概率是多大?
Input
第一行包含三个正整数M,N,K(1<=M,N<=500, 2<=K<=10^9)。
接下来M行每行N个小写字母,表示生成棋盘的模板。该模板至少包含两个不同的字母。
Output
以最简分数形式输出选出两个相同字符串的概率p/q。
Sample Input
输入1:
1 2 2
ab
输入2:
2 4 3
honi
hsin
输入3:
3 3 10
ban
ana
nab
Sample Output
输出1:
5/16
输出2:
19/512
输出3:
2/27
Data Constraint
62.5%的数据满足:M=N。
题解
首先题目要求的其实就是从每个位置开始,往8个方向拓展到长度k,每种字符串有多少个相同的,但是注意到k很大,所以我们可以用类似倍增的方法来做然后。。。好像没了QAQ
贴代码
const ma=30; ha=37; ha1=107; md=1000007; var f,g,v:array[0..500,0..500,0..31]of int64; s:array[0..505,0..505]of longint; h:array[0..1000008,1..3]of longint; go:array[1..8,1..2]of longint=((-1,1),(-1,0),(-1,-1),(0,1), (0,-1),(1,-1),(1,0),(1,1)); cc,cc1:array[0..31]of int64; i,j,k,l,n,m,x,y,z,t1,t2,be:longint; cs,pc,cs1,pc1:int64; ch:char; function gcd(x,y:int64):int64; begin if y=0 then exit(x) else exit(gcd(y,x mod y)); end; procedure hash(x,y:longint); var t,tt:longint; begin x:=x mod md; t:=x; tt:=y mod md; while (h[x,1]<>0) and ((h[x,1]<>t) or (h[x,2]<>tt)) do x:=x mod md+1; h[x,1]:=t; h[x,2]:=tt; inc(h[x,3]); end; procedure get; var x,y,xx,yy,zong:int64; begin x:=1; y:=0; zong:=8*n*m; x:=zong*zong; y:=0; for i:=0 to md-1 do if h[i,2]>0 then begin // xx:=zong*zong; y:=y+h[i,3]*h[i,3]; //y:=y*xx+x*yy; //x:=x*xx; end; xx:=gcd(x,y); x:=x div xx; y:=y div xx; writeln(y,'/',x); end; begin assign(input,'chessboard.in'); reset(input); assign(output,'chessboard.out'); rewrite(output); readln(m,n,k); for i:=1 to m do begin for j:=1 to n do begin read(ch); s[i,j]:=ord(ch)-96; g[i,j,0]:=s[i,j]; end; readln; end; cc[0]:=1; cc[1]:=ha; cc1[0]:=1; cc1[1]:=ha1; for i:=2 to ma do cc[i]:=(cc[i-1]*cc[i-1]) mod md; for i:=2 to ma do cc1[i]:=(cc1[i-1]*cc1[i-1]) mod md; for z:=1 to 8 do begin f:=g; v:=g; for l:=1 to ma do begin if 1<<l>k then begin be:=l-1; break; end; for i:=1 to m do begin for j:=1 to n do begin t1:=(m*k+i+go[z,1]*(1<<(l-1))-1) mod m+1; t2:=(n*k+j+go[z,2]*(1<<(l-1))-1) mod n+1; cs:=cc[l] mod md; f[i,j,l]:=(f[i,j,l-1]+cs*f[t1,t2,l-1]) mod md; cs:=cc1[l] mod md; v[i,j,l]:=(v[i,j,l-1]+cs*v[t1,t2,l-1]) mod md; end; end; end; for i:=1 to m do for j:=1 to n do begin x:=k; t1:=i; t2:=j; cs:=1; pc:=0; cs1:=1;pc1:=0; for l:=be downto 0 do if 1<<l<=x then begin pc:=(pc+cs*f[t1,t2,l]) mod md; pc1:=(pc1+cs1*f[t1,t2,l]) mod md; t1:=(m*k+t1+go[z,1]*(1<<l)-1) mod m+1; t2:=(n*k+t2+go[z,2]*(1<<l)-1) mod n+1; cs:=(cs*cc[l+1]) mod md; cs1:=(cs1*cc1[l+1]) mod md; //if l=be then cs:=(cs*ha) mod md; x:=x-(1<<l); end; hash(pc,pc1); end; end; get; close(input); close(output); end.
相关文章推荐
- 【JZOJ5045】【NOI2017模拟4.5】无限棋盘
- 【NOI2017模拟4.5】无限棋盘【哈希,字符串,倍增】
- 【NOI2017模拟4.5】机器人游戏
- 【NOI2017模拟4.5】数字格
- 【JZOJ5046】【NOI2017模拟4.5】机器人游戏
- 【NOI2017模拟4.5】机器人游戏【搜索,DP】
- NYOJ 45 棋盘覆盖 模拟+高精度
- 【NOI2017模拟6.26】A
- 快速切题 poj 2996 Help Me with the Game 棋盘 模拟 暴力 难度:0
- JZOI【NOI2017模拟3.30】轮回
- 【JZOJ5036】【NOI2017模拟3.30】原谅
- POJ2996-棋盘模拟
- NYOJ 45 棋盘覆盖 模拟+高精度
- 用二维数组模拟棋盘覆盖----采用分治法
- HDU 2073:无限的路【模拟】
- 【JZOJ 100019】【NOI2017模拟6.26】A
- [JZOJ5036]【NOI2017模拟3.30】原谅
- jzoj5043 【NOI2017模拟4.4】保持平衡 (可撤销贪心)
- 【NOI2017模拟3.30】原谅(计算几何,期望)
- 【JZOJ5037】【NOI2017模拟3.30】轮回