拆分的情况下,发现f数组本身并不是很好递推。

因为f(123)=f(123)/f(12+3)/f(1+2+3)。

然后考虑f可以怎么表示f(n)=a0*M^n M为转移矩阵。

然后发现 f(x+y)=a0*M(x+y), 所以只需要对M矩阵进行DP即可。

这样子每一个位置就可以表示为若干转移矩阵的和,然后就可以利用矩阵的相乘进行递推。

最后直接用原向量乘上转移矩阵即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define ll long long
#define F(i,j,k) for (ll i=j;i<=k;++i)
#define D(i,j,k) for (ll i=j;i>=k;--i)
const ll md=998244353; ll m,l;char s[505]; struct matrix{
ll x[6][6];
void init(){memset(x,0,sizeof x);}
void build1(){
init();
x[1][1]=1;
}
void build2(){
init();
F(i,1,m) x[i][1]=1;
F(i,1,m-1) x[i][i+1]=1;
}
void build3(){
init();
F(i,1,m) x[i][i]=1;
}
matrix operator * (matrix b) {
matrix ret;
ret.init();
F(i,1,m) F(j,1,m)
{
F(k,1,m)
ret.x[i][j]=ret.x[i][j]+x[i][k]*b.x[k][j];
ret.x[i][j]%=md;
}
return ret;
}
matrix operator + (matrix b) {
matrix ret;
ret.init();
F(i,1,m) F(j,1,m)
ret.x[i][j]=((ll)x[i][j]+(ll)b.x[i][j])%md;
return ret;
}
}dp[505],one,c[11][501],turn,now,ans; int main()
{
scanf("%s",s+1);l=strlen(s+1);
scanf("%lld",&m);
F(i,0,l) dp[i].init();
one.build1();
turn.build2();
c[0][0].build3();
F(i,1,10) c[i][0]=c[i-1][0]*turn;
F(i,1,l-1)
{
c[0][i]=c[0][i-1];
c[1][i]=c[10][i-1];
F(j,2,10)
{
c[j][i]=c[j-1][i]*c[10][i-1];
}
}
dp[0].build3();
F(i,1,l)
{
now.build3();
D(j,i,1)
{
now=now*c[s[j]-'0'][i-j];
dp[i]=dp[i]+dp[j-1]*now;
}
}
ans=dp[l]*one;
printf("%lld\n",ans.x[1][1]);
}

  

BZOJ 4037 [HAOI2015]数字串拆分 ——动态规划的更多相关文章

  1. bzoj 4037: [HAOI2015]数字串拆分【dp+矩阵加速】

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

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

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

  3. [HAOI2015]数字串拆分

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

  4. bzoj4037 [HAOI2015]数字串拆分

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

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

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

  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. [bzoj P4504] K个串

    [bzoj P4504] K个串 [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次 ...

  9. 解决 PHPExcel 长数字串显示为科学计数

    解决 PHPExcel 长数字串显示为科学计数 在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号. ...

随机推荐

  1. Java jar包查询下载方法

    做过java开发的工程师,对java应用所需jar包一定不会陌生.特别是有需要搭建开发环境时,对各种jar包的需求量就会很大. 如何快速的找到自己想要的jar包,是蛮多java工程师所面临的一个难题. ...

  2. sublime快捷键mark

    Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的多行时)Ctrl+L 选择整行(按住-继续选择下 ...

  3. Linux配置临时IP地址

    # ifconfig 查看网卡信息,如下图所示: # ifconfig eth0 192.168.0.107 eth0表示第一块网卡,Linux中所有的设配都是文件,所以eth0是第一块网卡的文件名, ...

  4. 使用python查询天气

    python主代码 weather.py import urllib2 import json from city import city cityname = raw_input('你想查哪个城市的 ...

  5. 分布式锁----浅析redis实现

    引言大概两个月前小伙伴问我有没有基于redis实现过分布式锁,之前看redis的时候知道有一个RedLock算法可以实现分布式锁,我接触的分布式项目要么是github上开源学习的,要么是小伙伴们公司项 ...

  6. react中的setState的使用和深入理解

    前端框架从MVC过渡到MVVM.从DOM操作到数据驱动,一直在不断的进步着,提升着, angular中用的是watcher对象,vue是观察者模式,react就是state了,他们各有各的特点,没有好 ...

  7. nyoj-47-过河问题|POJ-1700-Crossing River

    http://acm.nyist.net/JudgeOnline/problem.php?pid=47 http://poj.org/problem?id=1700 解题思路:求最少需要多少时间才能都 ...

  8. tomcat BIO 、NIO 、AIO

    11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.apr模式以及后来自己测试的一些性能结果. 原理方面的资料都是从网上找 ...

  9. POI导出excel项目(webwork)实例

    后台action: public String exportExcel(){ this.setUserList(this.getUserService().findUserInfosByGroupID ...

  10. ios之UISearchBar

    当你在seachBar中输入字母之前的时候,只是用鼠标选中searchBar的时候,如图 终端输出截图如下:(这个时候调用先shouldBeginEditing,之后调用didBeginEditing ...