博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【以前的空间】bzoj1009 [HNOI2008]GT考试
阅读量:5060 次
发布时间:2019-06-12

本文共 2811 字,大约阅读时间需要 9 分钟。

  动态规划+kmp+矩阵快速幂

  关于这题可以写出一个dp方程(f[i,j]表示准考证前i位中后j位为不吉利的数字的前j位的情况的个数)

  f[i,j]=Σf[i-1,k],其中j表示不吉利数字前k个数字加上某个数字后变成为不吉利数字的前j位(比如不吉利数字122123,然后现在k=5,那么如果填个3,j=6(123123);填个2,j=3(122);填个1,j=1(1);填个0,j=0。

  然后我们就可以发现……好像可以用kmp算法来优化每次k+某个数字可以转移到的j的位置……因为j包括了前k个数字,那么j一定是在k的失配函数+1位或者不存在。

  但是这样的话时间复杂度依然因为n过大而报表……。

  于是神奇的矩阵来了!

  没有发现似乎式子是递推式么?!

  也就是F(n)是可以通过F(n-1)得到的!F(n)表示f[n,0],f[n,1],f[n,2]……f[n,m-1]的集合,或者说……一个1*(m-1)的矩阵。

  矩阵的定义白书有句话说的特别好:“把一个向量v变成另一个向量v',并且v'的每个分量都是v各个分量的线性组合”。什么是线性组合……就是一个线性方程组!对于这题来说,线性方程组就是:

  F(n)=A*F(n-1) (这里A叫友矩阵,其实就是转移关系)

  如果写出矩阵,式子就变成

  [f(n,0)  ]     [a[0,0]  ,a[1,0]  ,a[2,0]  ,……,a[m-1,0]  ]   [f(n-1,0)  ]

  [f(n,1)  ]     [a[0,1]  ,a[1,1]  ,a[2,1]  ,……,a[m-1,1]  ]   [f(n-1,1)  ]

  [f(n,2)  ]   = [a[0,2]  ,a[1,2]  ,a[2,2]  ,……,a[m-1,2]  ] * [f(n-1,2)  ]

  [ ……   ]     [  ……                                     ]   [ ……     ]

  [f(n,m-1)]     [a[m-1,1],a[m-1,2],a[m-1,3],……,a[m-1,m-1]]   [f(n-1,m-1)]

  式子中的a[i,j]表示不吉利数字前i位加上某个数字后可以转的j位的数量。

  前面说的线性组合是什么意思?矩阵其实是一个线性方程组,形式就是:

  a[0,0]*f[n-1,0]+a[1,0]*f(n-1,1)+a[2,0]*f(n-1,2)+……+a[m-1,0]*f[n-1,m-1]=f[n,0];

  a[0,1]*f[n-1,0]+a[1,1]*f(n-1,1)+a[2,1]*f(n-1,2)+……+a[m-1,1]*f[n-1,m-1]=f[n,1];

  a[0,2]*f[n-1,0]+a[1,2]*f(n-1,1)+a[2,2]*f(n-1,2)+……+a[m-1,2]*f[n-1,m-1]=f[n,2];

  ………………………………………………… 

  a[0,m-1]*f[n-1,0]+a[1,m-1]*f(n-1,1)+a[2,m-1]*f(n-1,2)+……+a[m-1,m-1]*f[n-1,m-1]=f[n,m-1]

 

  看出来了么?

 

  回到题目上,如果递推算F(n),显然不行,但是我们有一个递推式F(n)=A*F(n-1),它可以化为F(n)=A^n*F(0)。

  那么现在要做的就是如何优化A^n,想到快速幂?是的,矩阵也有快速幂(具体到网上找吧,这就不是理解方面的了)

  然后答案就是F(n)=A^n*F(0)。但是这个F(0)没什么意义啊,f[0,0]=1,其他都等于0。

  这样像上面那样写出线性方程组的形式你就发现这个F(n)=a[0,0]+a[0,1]+a[0,2]+……+a[0,m-1],那最后就没有必要算F(0)*A^n,直接算上a[0,i]的和就行了!

  然后联系一下A的意义……是不是有点感觉?A^i就是表示a[j,k]原来是前j位递推i次后能变成前k位的方案!蒟蒻感觉好神奇!

 

  然后就好像初步学会了矩阵快速幂优化……

2345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061type  arr=array[0..25,0..25]of longint; var  a,c,tmp:arr;  b,p:array[0..30]of longint;  i,j,k,l,n,m,mm,sum:longint;  ch:char;  procedure mul(var x,y:arr);var  i,j,k:longint;begin  for i:=0 to m-1 do    for j:=0 to m-1 do begin      tmp[i,j]:=0;      for k:=0 to m-1 do        tmp[i,j]:=(tmp[i,j]+x[i,k]*y[k,j])mod mm;    end;  for i:=0 to m-1 do    for j:=0 to m-1 do      x[i,j]:=tmp[i,j];end;  begin  readln(n,m,mm);  for i:=1 to m do begin    read(ch);    b[i]:=ord(ch)-ord('0');  end;  j:=0;  p[1]:=0;  for i:=2 to m do begin    while (j>0) and (b[j+1]<>b[i]) do j:=p[j];    if b[j+1]=b[i] then inc(j);    p[i]:=j;  end;  for i:=0 to m-1 do    for j:=0 to 9 do begin      k:=i;      while (k>0) and (b[k+1]<>j) do k:=p[k];      if b[k+1]=j then inc(k);      if k<>m then c[i,k]:=(c[i,k]+1)mod mm;    end;  fillchar(a,sizeof(a),0);  for i:=0 to m-1 do    a[i,i]:=1;  while n>0 do begin    if n and 1=1 then mul(a,c);    mul(c,c);    n:=n>>1;  end;  sum:=0;  for i:=0 to m-1 do    sum:=(sum+a[0,i]) mod mm;  writeln(sum);  readln;  readln;end.
View Code

 

转载于:https://www.cnblogs.com/Macaulish/p/6492091.html

你可能感兴趣的文章
使用 JointCode.Shuttle 访问任意 AppDomain 的服务
查看>>
hdoj 1846 Brave Game(巴什博弈)
查看>>
Round #345 B. Beautiful Paintings(Div.2)
查看>>
51nod 1018排序
查看>>
sqlite的坑
查看>>
digitalocean --- How To Install Apache Tomcat 8 on Ubuntu 16.04
查看>>
linux swoole
查看>>
An Easy Problem?! - POJ 2826(求面积)
查看>>
【题解】[P4178 Tree]
查看>>
Jquery ui widget开发
查看>>
css3实现循环执行动画,且动画每次都有延迟
查看>>
更改git仓库地址
查看>>
有标号DAG计数 [容斥原理 子集反演 组合数学 fft]
查看>>
Recipe 1.4. Reversing a String by Words or Characters
查看>>
Rule 1: Make Fewer HTTP Requests(Chapter 1 of High performance Web Sites)
查看>>
sql注入
查看>>
「破解」Xposed强
查看>>
Linux 平台下 MySQL 5.5 安装 说明 与 示例
查看>>
src与href的区别
查看>>
ABAP工作区,内表,标题行的定义和区别
查看>>