遥控车_vijos1458_纪中1724_水

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如下

f[i][j]=f[i1][j]+f[i2][j1]

表示前i辆车有j辆和右边交换位置,因为和右边换等同于和左边换所以不作考虑
然后你就会发现j是个酱油
设f[i]表示前i辆车的总方案数,则
f[i]=f[i1]+f[i2]

这是什么???!!!!
斐波那契数列
由于数据大,要打高精度
尝试过矩阵乘法,然后要打高精加和高精乘,于是我可耻地放弃了

代码/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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值