您的位置:首页 > 其它

【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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: