Description
平平带着韵韵来到了游乐园,看到了n辆漂亮的遥控车,每辆车上都有一个唯一的名字name[i]。韵韵早就迫不及待地想玩名字是s的遥控车。可是韵韵毕竟还小,她想象的名字可能是一辆车名字的前缀(也就是说能确定一个i,使s是name[i]的前缀),这时她就能玩第i辆车;或者是一个无中生有的名字,即s不是任何一辆车名字的前缀,这时候她什么也不能玩。
你需要完成下面的任务:
1.韵韵想了m个她想要的名字,请告诉她能玩多少次。
2.由于管理员粗心的操作,导致每辆车的摆放位置都可能出现微小的差错,原来第i辆车现在的位置可能是i-1、i、i+1中的任意一个(第1辆车的位置不可能是0,第n辆车的位置不可能是n+1)。请你计算出共有多少种可能的排列。
注:数据保证当s是name[i]的前缀时,i是唯一确定的。一辆车可以玩多次。
Input
第一行是2个正整数n、m。
接下来n行,每行1个字符串name[i],表示第i辆车的名字。
接下来m行,每行1个字符串s,表示韵韵想要的名字。
Output
第一行输出韵韵能玩的次数。
第二行输出共有多少种可能的排列。
Sample Input
4 4
Abcd
DeF
AAa
aBccc
Ab
AA
AbC
aBcc
Sample Output
3
5
Hint
对于题目涉及到的字符串严格区分大小写,且长度小于255。
对于20%的数据 n≤10,m≤10;
对于40%的数据 n≤1000,m≤1000;
对于100%的数据 n≤10000,m≤10000。
题解
抱着第一题不会太难的心态看,然后就懵了 囧
第一问:
查找,判断+统计。普通的暴枚会TLE,用一个神奇的优化方法把字符串转成类似前缀和的东西比较,速度骤然上升
第二问:
先是一本正经列了一个2维dp如下
表示前i辆车有j辆和右边交换位置,因为和右边换等同于和左边换所以不作考虑
然后你就会发现j是个酱油
设f[i]表示前i辆车的总方案数,则
这是什么???!!!!
斐波那契数列
由于数据大,要打高精度
尝试过矩阵乘法,然后要打高精加和高精乘,于是我可耻地放弃了
代码/pas:
type
num=record
v:array[1..3000]of longint;
len:Longint;
end;
var
n,m,i,j,ans:Longint;
st:array[0..10000,0..300]of real;
l:array[0..10000]of longint;
a:array[0..10000]of real;
u,v,w:num;
s:string;
function add(x,y:num):num;
var
i,t:longint;
begin
fillchar(add,sizeof(add),0);
add.len:=y.len;
if x.len>y.len then add.len:=x.len;
t:=0;
for i:=1 to add.len do
begin
add.v[i]:=(x.v[i]+y.v[i]+t)mod 10;
t:=(x.v[i]+y.v[i]+t)div 10;
end;
if t<>0 then
begin
inc(add.len);
add.v[add.len]:=t;
end;
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(s);
for j:=1 to length(s) do
st[i,j]:=st[i,j-1]*1.9+ord(s[j]);
end;
for i:=1 to m do
begin
readln(s);
l[i]:=length(s);
for j:=1 to length(s) do
a[i]:=a[i]*1.9+ord(s[j]);
end;
for i:=1 to n do
for j:=1 to m do
if st[i,l[j]]=a[j] then
inc(ans);
writeln(ans);
u.len:=1;
u.v[1]:=1;
v.len:=1;
v.v[1]:=1;
for i:=2 to n do
begin
w:=add(u,v);
u:=v;
v:=w;
end;
for i:=w.len downto 1 do write(w.v[i]);
writeln;
end.