首先f长得就很像能矩阵优化的,先构造转移矩阵(这里有一点神奇的地方,我看网上的blog和我构造的矩阵完全不一样还以为我的构造能力又丧失了,后来惊奇的发现我把那篇blog里的构造矩阵部分换成我的构造方式,交了一下完全没问题2333,并不知道为啥)

好久没写矩阵加速了,顺便说一下我的构造方法吧:

首先明确转移矩阵的目的,设m为构成f[i]的最小项f[i-m],也就是f[i]=f[i-m]+f[i-...]+f[i-...]+....,其中i-m是最小的。我们需要构造一个m大小的矩阵,使得{f[i-m],f[i-m+1].....f[i-1}乘上这个正方形矩阵变成{f[i-m+1],f[i-m+2]....f[i]}然后因为矩阵乘法是一行乘一列,所以每个右边的每个f[i]都对应了一行矩阵和左边的每项依次相乘。拿这道题的递推式,m=3为例:



以上,我也不知道我在说什么。

然后这道题的精髓在于它使用f的矩阵进行g的dp。设f[i]为前i位的答案,因为矩阵乘法的结合律,我们可以记\( g[i]=\sum_{j=1}^{m}g[j]*c[j+1][i] \)。然后考虑如何预处理出c,可以设c[i][j]为i这个数(1<=i<=9)的\( j^{10} \)次(假装高精)。

总之,一道好题。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=505,mod=998244353;
int n,m;
char s[N];
struct qwe
{
int a[7][7];
void init()
{
memset(a,0,sizeof(a));
}
void pre()
{
memset(a,0,sizeof(a));
for(int i=1;i<=m;i++)
a[i][i]=1;
}
qwe operator * (const qwe &b) const
{
qwe c;
c.init();
for(int k=1;k<=m;k++)
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%mod)%mod;
return c;
}
qwe operator + (const qwe &b) const
{
qwe c;
c.init();
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
c.a[i][j]=(b.a[i][j]+a[i][j])%mod;
return c;
}
}f[N],a,c[15][N];
qwe ksm(qwe a,int b)
{
qwe r;
r.pre();
while(b)
{
if(b&1)
r=r*a;
a=a*a;
b>>=1;
}
return r;
}
int main()
{
scanf("%s%d",s+1,&m);
n=strlen(s+1);
for(int i=1;i<=n;i++)
s[i]-='0';
for(int i=1;i<m;i++)
a.a[i][i+1]=1;
for(int i=1;i<=m;i++)
a.a[m][i]=1;
c[0][1].pre();
for(int i=1;i<=9;i++)
{
c[i][1]=c[i-1][1]*a;
for(int j=2;j<=n;j++)
c[i][j]=ksm(c[i][j-1],10);
}
f[0].a[1][m]=1;
for(int i=1;i<=n;i++)
{
qwe tmp=c[s[i]][1];
for(int j=i-1;j>=0;j--)
{
f[i]=f[i]+f[j]*tmp;
if(j&&s[j])
tmp=tmp*c[s[j]][i-j+1];
}
}
printf("%d\n",f[n].a[1][m]);
return 0;
}

bzoj 4037: [HAOI2015]数字串拆分【dp+矩阵加速】的更多相关文章

  1. BZOJ 4037 [HAOI2015]数字串拆分 ——动态规划

    拆分的情况下,发现f数组本身并不是很好递推. 因为f(123)=f(123)/f(12+3)/f(1+2+3). 然后考虑f可以怎么表示f(n)=a0*M^n M为转移矩阵. 然后发现 f(x+y)= ...

  2. 洛谷3176 [HAOI2015]数字串拆分 (矩阵乘法+dp)

    qwq真的是一道好题qwq自己做基本是必不可能做出来的. 首先,如果这个题目只是求一个\(f\)数组的话,那就是一道裸题. 首先,根据样例 根据题目描述,我们能发现其实同样数字的不同排列,也是属于不同 ...

  3. BZOJ4037:[HAOI2015]数字串拆分——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4037 你有一个长度为n的数字串.定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时 ...

  4. bzoj4037 [HAOI2015]数字串拆分

    Description 你有一个长度为n的数字串.定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5,分别为4=1+1+1+1你可以将这个数字串分割成若干个数字(允许前导 ...

  5. [HAOI2015]数字串拆分

    题目描述 你有一个长度为n的数字串.定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5,分别为4=1+1+1+1你可以将这个数字串分割成若干个数字(允许前导0),将他们加 ...

  6. loj#2128. 「HAOI2015」数字串拆分 矩阵乘法

    目录 题目链接 题解 代码 题目链接 loj#2128. 「HAOI2015」数字串拆分 题解 \(f(s)\)对于\(f(i) = \sum_{j = i - m}^{i - 1}f(j)\) 这个 ...

  7. 【LOJ】#2128. 「HAOI2015」数字串拆分

    题解 题中给的函数可以用矩阵快速幂递推 我们记一个数组dp[i](这个数组每个元素是一个矩阵)表示从1到i所有的数字经过拆分矩阵递推的加和 转移方法是 \(dp[i] = \sum_{j = 0}^{ ...

  8. HihoCoder - 1807:好的数字串 (KMP DP)

    Sample Input 6 1212 Sample Output 298 给定一个数字字符串S,如果一个数字字符串(只包含0-9,可以有前导0)中出现且只出现1次S,我们就称这个字符串是好的. 例如 ...

  9. [BZOJ 4033] [HAOI2015] T1 【树形DP】

    题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...

随机推荐

  1. Access数据库密码破解 C#

    private string GetPassword(string file) { // 未加密的文件0x42开始至0x61之前的每间隔一字节的数值 byte[] baseByte = { 0xbe, ...

  2. webpack体积优化篇二(GZ压缩)

    这里我列举几个常用的能够用于减少包体大小的插件,我们可以根据项目需求选择性的使用: compression-webpack-plugin :该插件能够将资源文件压缩为.gz文件,并且根据客户端的需求按 ...

  3. MySQL注释(转)

    MySQL支持3种注释风格: 1.从‘#’字符从行尾. 2.从‘-- ’序列到行尾.请注意‘-- ’(双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格.tab.换行符等等). 3.从/ ...

  4. VB程序逆向反汇编常见的函数(修改版)

    VB程序逆向常用的函数 1) 数据类型转换: a) __vbaI2Str    将一个字符串转为8 位(1个字节)的数值形式(范围在 0 至 255 之间) 或2 个字节的数值形式(范围在 -32,7 ...

  5. 安装软件:/lib/ld-linux.so.2: bad ELF interpreter解决

    http://linux.chinaitlab.com/set/928509.html 我们在CentOS系统中安装软件:/lib/ld-linux.so.2: bad ELF interpreter ...

  6. Shell 脚本小试牛刀(5) -- 超便捷脚本之高速ssh 登录其它主机

    假设你也是以Linux 为工作环境的童鞋,那么此文真是捷报!由于我的学习/工作中(特别是近期玩耍树莓派)常常会使用到ssh 登录其它主机,而每次使用ssh 登录都须要输入老长一大串让我非常烦.所以我写 ...

  7. Redis Server分布式缓存编程

    这篇文章我将介绍如果用最简洁的方式配置Redis Server, 以及如何使用C#和它交互编程 一. 背景介绍 Redis是最快的key-value分布式缓存之一 缺点: 没有本地数据缓冲, 目前还没 ...

  8. 解决Struts配置文件里无提示信息的问题

    (1)在struts2配置文件编写的时候.有可能无法提示所有信息,在配置文件里打个"<" 后,并没有不论什么的提示信息(使用快捷键Alt+/ 也不提示) 原因是下边的  &q ...

  9. 安卓版本和Api Level

    Platform Version API Level VERSION_CODE Notes Android 4.4 19 KITKAT Platform Highlights Android 4.3 ...

  10. 图像处理之基础---boxfiter

    http://blog.sina.com.cn/s/blog_7221228801019yg2.html DSP6000图像位移与变形典型算法 http://blog.csdn.net/anson20 ...