【HAOI2015】bzoj4037 数字串拆分

2023-11-07 19:59

本文主要是介绍【HAOI2015】bzoj4037 数字串拆分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description
你有一个长度为n的数字串。定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5,分别为4=1+
1+1+1你可以将这个数字串分割成若干个数字(允许前导0),将他们加起来,求f,并求和。比如g(123)=f(1+2+3)
+f(1+23)+f(12+3)+f(123)。已知字符串和m后求答案对998244353(7×17×223+1,一个质数)取模后的值。 Input

第一行输入一个字符串,第二行输入m Output

仅输出一个数表示答案

构造 m×m 的转移矩阵 A 满足ai,j=1当且仅当 j=1 i+1=j 。可以发现, fn=An1,1
接下来考虑在字符串上dp,但是发现如果直接做不满足乘法分配律,也就是不能写成 dpi=i1j=0dpjfj+1..i 。但是因为 f 可以写成矩阵的幂的形式,这样就可以提取公因式,满足了分配律。
在算一段区间的时候,可以预处理出来x10y的答案,然后直接相乘,注意不要写成 O(n3)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int mod=998244353;
int m,n;
char s[510];
struct mat
{int a[6][6];void init(){for (int i=1;i<=m;i++)for (int j=1;j<=m;j++)a[i][j]=(j==1||i+1==j);}void I(){for (int i=1;i<=m;i++)for (int j=1;j<=m;j++)a[i][j]=(i==j);}mat operator + (const mat &mm) const{mat ret;for (int i=1;i<=m;i++)for (int j=1;j<=m;j++)ret.a[i][j]=(a[i][j]+mm.a[i][j])%mod;return ret;}mat operator * (const mat &mm) const{mat ret;for (int i=1;i<=m;i++)for (int j=1;j<=m;j++){ret.a[i][j]=0;for (int k=1;k<=m;k++)ret.a[i][j]=(ret.a[i][j]+(LL)a[i][k]*mm.a[k][j]%mod)%mod;}return ret;}mat pow(int x){mat ret,base;ret.I();for (int i=1;i<=m;i++)for (int j=1;j<=m;j++)base.a[i][j]=a[i][j];while (x){if (x&1) ret=ret*base;base=base*base;x>>=1;}return ret;}
}f[10][510],dp[510],t;
mat cal(int l,int r)
{mat ret;ret.I();for (int i=l;i<=r;i++)ret=ret*f[s[i]-'0'][r-i];return ret;
}
int main()
{scanf("%s",s+1);n=strlen(s+1);scanf("%d",&m);for (int i=0;i<=n;i++) f[0][i].I();f[1][0].init();for (int i=1;i<=n;i++) f[1][i]=f[1][i-1].pow(10);for (int i=2;i<=9;i++)for (int j=0;j<=n;j++)f[i][j]=f[i-1][j]*f[1][j];dp[0].I();for (int i=1;i<=n;i++){t=f[s[i]-'0'][0];for (int j=i-1;j>=0;j--){dp[i]=dp[i]+dp[j]*t;if (j) t=t*f[s[j]-'0'][i-j];}}printf("%d\n",dp[n].a[1][1]);
}

这篇关于【HAOI2015】bzoj4037 数字串拆分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/365959

相关文章

Python进行PDF文件拆分的示例详解

《Python进行PDF文件拆分的示例详解》在日常生活中,我们常常会遇到大型的PDF文件,难以发送,将PDF拆分成多个小文件是一个实用的解决方案,下面我们就来看看如何使用Python实现PDF文件拆分... 目录使用工具将PDF按页数拆分将PDF的每一页拆分为单独的文件将PDF按指定页数拆分根据页码范围拆分

隐私计算实训营:SplitRec:当拆分学习遇上推荐系统

拆分学习的概念 拆分学习的核心思想是拆分网络结构。每一个参与方拥有模型结构的一部分,所有参与方的模型合在一起形成一个完整的模型。训练过程中,不同参与方只对本地模型进行正向或者反向传播计算,并将计算结果传递给下一个参与方。多个参与方通过联合模型进行训练直至最终收敛。 一个典型的拆分学习例子: Alice持有数据和基础模型。Bob只有数据、基础模型和fuse模型。 Alice使用自己的数据

动态规划---单词拆分

题目: 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 思路:本题属于完全背包问题,字符串s的长度为背包容量,字符串列表wordDict中的每一个元素相当于物品。 动态规划五部曲: 1.确定dp数组及含义 dp数组为元素类型是布

代码随想录:343. 整数拆分

343. 整数拆分   class Solution {public:int integerBreak(int n) {int dp[100]={0};//拆分i的最大乘积为dp[i]dp[1]=1;//初始化,主要是为了dp[2]初始for(int i=2;i<=n;i++){for(int j=1;j<i;j++){ dp[i]=max(dp[i],max(j,dp[j])*ma

【动态规划】343. 整数拆分

力扣链接:343. 整数拆分 - 力扣(LeetCode) dp数组的含义:dp[i]表示对i拆分,得到最大的积为dp[i] 递推公式:拆成两个数是 j*(i-j),拆成三个及以上是 j*dp[i-j],所以递推公式取两者大值 遍历顺序:从小到大 public int integerBreak(int n) {int[] dp = new int[n+1];dp[1]=0;dp[2]=

2157. 优秀的拆分(power)

代码 #include<bits/stdc++.h>using namespace std;int a[10001];int main(){int n,t=1,k=0;bool flag=false;cin>>n;if(n%2==1) {cout<<-1;return 0;}while(n>0){if(n%2==1){k++;a[k]=t; }n=n/2;t=t*2;}if(k

NumPy(七):拆分【hsplit】【vsplit】

数组拆分:输出结果为列表,列表中元素为数组 numpy.hsplit(ary, indices_or_sections):将数组水平(逐列)拆分为多个子数组 → 按列拆分numpy.vsplit(ary, indices_or_sections)::将数组垂直(行方向)拆分为多个子数组 → 按行拆 import numpy as np# 数组拆分:输出结果为列表,列表中元素为数组ar = np

python自动化操作PDF,拆分pdf合并pdf,提取pdf内容

第三方库介绍 Python 操作 PDF 会用到两个库,分别是:PyPDF2 和 pdfplumber。         PyPDF2 可以更好的读取、写入、分割、合并PDF文件;         pdfplumber 可以更好的读取 PDF 文件中内容和提取 PDF 中的表格,主要应用于机器生成的 PDF,而非扫描的PDF文档。         由于这两个库都不是 Python 的标准

代码随想录训练营day34|62.不同路径,63. 不同路径 II,343.整数拆分,96.不同的二叉搜索树

不同路径1 题目 题目并不难想,每一个点只有两种走到的方法,要么从左侧来,要么从上侧来,所以 dp[i][j]=dp[i-1][j]+dp[i][j-1]; vector<vector<int>> dp(m,vector<int>(n,0)); for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(i>0&&j>0){dp[i][j]=dp[i-1][

拆分英文名

题目内容: 从键盘输入某同学的英文名(小写输入,假设学生的英文名只包含3个字母。如: tom),编写程序在屏幕上输出该同学的英文名,且首字母大写(如: Tom)。同时输出组成该英文名的所有英文字符在26个英文字母中的序号。 以下为程序的输出示例: input your English name: tom↙ Tom t:20 o:15 m:13 输入格式