首先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. ArcEngine读取ShapeFile时,出现乱码的解决方案

    ArcEngine读取ShapeFile时,如果用LicenseControl的话,字段中含有汉字时可以正常使用,当使用LicenseInitializer进行初始化时,读取含有汉字的字段时,就会出现 ...

  2. 【Mongodb教程 第一课补加课2 】MongoDB下,启动服务时,出现“服务没有响应控制功能”解决方法

    如图,如果通过下列代码,添加服务后,使用net start命令出现这样的问题时,可以参考下我的解决方法. D:\MongoDB>mongod --dbpath D:\MongoDB\Data - ...

  3. SLF4J: Failed to load class的问题及解决

    今天在做接口测试,一运行测试程序,就跳出这样一个大大的错误: SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”. SLF4 ...

  4. 安装SQLserver2008时出现的错误

    1.SQLserver2008提示必须重新启动计算机才干够继续安装.解决方法例如以下: 在開始->执行中输入regedit,到HKEY_LOCAL_MACHINE\SYSTEM\CurrentC ...

  5. Sublime Text 3设置吊炸天PHP开发环境

    @heiyeluren @created: 2016/5/31 @last modify: 2016/7/8 1. 下载安装Sublime Text 3 http://www.sublimetext. ...

  6. 对于api安全性的思考

    目前的情况下api被很多地方应用,随之而来的是api的安全性问题. 我所认识到的安全性问题有以下几个方面: 1.DDoS(拒绝服务攻击),接口被恶意调用,使真实的用户无法享受到正常畅通的服务.     ...

  7. Koa2学习(四)POST请求

    Koa2学习(四)POST请求 接受请求 POST请求的数据实体,会根据数据量的大小进行分包传送. 当node.js后台收到post请求时,会以buffer的形式将数据缓存起来.Koa2中通过ctx. ...

  8. JavaScript中面向对象那点事

    鉴于自己在JavaScript这方面比較薄弱.所以就找了一本书恶补了一下(被称为犀利书的JavaScript权威指南).书的内容尽管多了点,但这也充分说明了js中的东西还是挺多的.尽管我们的定位不是前 ...

  9. 常用的Atom插件

    1.simplified-chinese-menu 2.tree-view-finder 3.minimap 4.linter和linter-jshint 5.linter-js-standard 6 ...

  10. mysql workbench快捷键

    注释/取消注释, ctrl+/   暂时不知道怎么设置(原配置是 ctrl+divide)格式化sql语句(美化sql语句), ctrl+b