当前位置: 首页 > news >正文

P3176 [HAOI2015] 数字串拆分 - Link

题意

给出一个数字串 \(s_0\) 和一个数 \(m\)
定义 \(f(n)\) 为把 \(n\) 拆分成若干个 \(1∼m\) 的数的和的方案数(有序)。
定义 \(g(n)\) 为将数字串 \(n\) 分成若干个数字(可以有前导 \(0\)),设祂们和为 \(x\),则 \(g(n)\) 为所有情况下 \(f(x)\) 的和。
\(|s_0|\le500,1\le m\le5\)

思路

显然,有 \(f(n)=\sum_{i=1}^mf(n-i)\)。可以用一个矩阵刻画。由于矩阵有分配律和结合律,可以记忆化搜索。记录当前到哪一位,当前这段数从哪里开始。每个位置有两种情况:把结束当前段和不结束当前段。复杂度为 \(\mathcal O(|s_0|^3m^3)\)。似乎承受不了。记录 \(F_{i,j}=f(s_0[i:j])\),这个可以 \(\mathcal O(|s_0|^2m^3)\) 预处理,搜索时直接用 \(F\) 即可。
时间复杂度 \(\mathcal O(|s_0|^2m^3)\)

代码

// Problem: P3176 [HAOI2015] 数字串拆分
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3176
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<bits/stdc++.h>
using namespace std;
namespace IO{template<typename T>inline void read(T&x){x=0;char c=getchar();bool f=0;while(!isdigit(c)) c=='-'?f=1:0,c=getchar();while(isdigit(c)) x=x*10+c-'0',c=getchar();f?x=-x:0;}template<typename T>inline void write(T x){if(x==0){putchar('0');return ;}x<0?x=-x,putchar('-'):0;short st[50],top=0;while(x) st[++top]=x%10,x/=10;while(top) putchar(st[top--]+'0');}inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}inline void write(char c){putchar(c);}inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
template<int mod>struct Modint{int z;Modint(){z=0;}Modint(int x){x%=mod;z=x<0?x+mod:x;}Modint(long long x){x%=mod;z=x<0?x+mod:x;}Modint(short x){x%=mod;z=x<0?x+mod:x;}Modint(char x){x%=mod;z=x<0?x+mod:x;}Modint(bool x){x%=mod;z=x<0?x+mod:x;}friend Modint operator+(Modint t,Modint t2){Modint ans;ans.z=(t.z+t2.z)%mod;return ans;}friend Modint operator*(Modint t,Modint t2){Modint ans;ans.z=1ll*t.z*t2.z%mod;return ans;}friend Modint operator-(Modint t,Modint t2){Modint ans;ans.z=(t.z-t2.z)%mod;return ans;}Modint operator-()const{return (Modint){-z};}Modint operator<<(const int t)const{Modint ans;ans.z=(z<<t)%mod;return ans;}Modint operator>>(const int t)const{Modint ans;ans.z=(z>>t)%mod;return ans;}Modint&operator+=(const Modint t){z=(z+t.z)%mod;return *this;}Modint&operator*=(const Modint t){z=1ll*z*t.z%mod;return *this;}Modint&operator-=(const Modint t){z=(z-t.z)%mod;return *this;}Modint&operator<<=(const int t){z=(z<<t)%mod;return *this;}Modint&operator>>=(const int t){z=(z>>t)%mod;return *this;}Modint&operator++(){z++,z%=mod;return *this;}Modint&operator--(){z--,z%=mod;return *this;}Modint operator++(int){Modint ls=*this;z++,z%=mod;return ls;}Modint operator--(int){Modint ls=*this;z--,z%=mod;return ls;}friend Modint ksm(Modint a,int b){Modint ans=1;while(b){if(b&1) ans=ans*a;a=a*a,b>>=1;}return ans;}friend void read(Modint&z){int x=0;char c=getchar();bool f=0;while(!isdigit(c)) c=='-'?f=1:0,c=getchar();while(isdigit(c)) x=(x*10ll+c-'0')%mod,c=getchar();f?x=-x:0;z.z=x;}friend void write(Modint x){x.z<0?x.z+=mod:0;write(x.z);}
};
const int mod=998244353,maxm=6,maxn=510;
#define M Modint<mod>
int n,m;
struct Matrix{M a[maxm][maxm];Matrix(){memset(a,0,sizeof(a));}Matrix operator*(const Matrix b)const{Matrix c;for(int i=1;i<=m;i++) for(int k=1;k<=m;k++) for(int j=1;j<=m;j++) c.a[i][j]+=a[i][k]*b.a[k][j];return c;}Matrix operator+(const Matrix b)const{Matrix c;for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) c.a[i][j]=a[i][j]+b.a[i][j];return c;}
};
Matrix fr[maxn][maxn],base,f[maxn][maxn];
string s;
bool flag[maxn][maxn];
Matrix dfs(int u,int lt){if(flag[u][lt]) return f[u][lt];if(u==1) return fr[u][lt];flag[u][lt]=1;Matrix ans;ans=ans+dfs(u-1,lt)+dfs(u-1,u-1)*fr[u][lt];return f[u][lt]=ans;
}
signed main(){read(s,m);for(int i=1;i<=m;i++) base.a[i][1]=1;for(int i=2;i<=m;i++) base.a[i-1][i]=1;n=s.size();s=" "+s;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) fr[i][i-1].a[j][j]=1;for(int j=i;j<=n;j++){fr[i][j]=fr[i][j-1];Matrix ls=fr[i][j];for(int c=1;c<=9;c++) fr[i][j]=fr[i][j]*ls;ls=base;for(int c=1;c<=s[j]-'0';c++) fr[i][j]=fr[i][j]*ls;}}Matrix ans=dfs(n,n);write(ans.a[1][1]);return 0;
}
http://www.jsqmd.com/news/899292/

相关文章:

  • ChatGPT vs Claude 4 vs Gemini 2.5 Pro vs Qwen3 vs DeepSeek-R1:谁在中文长文本理解、代码生成与合规性上真正胜出?
  • 为什么你的ChatGPT写不出《雨巷》?——基于2372首训练诗集的语义张力分析,揭示诗歌生成中「陌生化」失效的3个隐藏断点
  • Visio导出矢量图总带白边?一个隐藏的‘打印属性’设置就能搞定(保姆级避坑教程)
  • 别再手动写手册了!:2024最新版ChatGPT员工手册生成工作流(含ISO 27001信息安全部分自动嵌入)
  • 构建内容审核辅助系统时集成多模型以提高判断准确性
  • 别再用SoapUI了!Postman搞定老旧WebService接口测试的保姆级教程
  • 基于形式化方法与网络流优化的自主系统反应式测试合成
  • 终极免费QQ音乐格式转换工具QMCDecode:三步解锁加密音频,实现跨设备播放自由
  • 如何快速上手VPKEdit:游戏资源包编辑完整指南
  • 编程高手必备:IT超能力技能树
  • ALDRED协议:水下异步传感器网络如何实现低延迟与高能效通信
  • 三维CFD混合模型与实时预警系统:破解溃坝洪水模拟精度与效率难题
  • 从规则执行到认知决策:AI芯片分布式系统v1.1的LLM驱动架构演进
  • 基于鲸鱼优化算法的自适应图像隐写技术:原理、实现与优化
  • 2026年威海连锁海鲜餐馆推荐:5家正规门店深度测评,首选海滨小院 - 资讯纵览
  • DKVMN-KAPS:融合知识吸收与解题能力的个性化知识追踪模型详解
  • 模型检验DAAC算法:高效检测所有反例,破解系统验证难题
  • 埃用仪器|NECPS 2026青岛技术研讨会圆满收官
  • 脑机接口技术:从神经信号解码到临床应用的挑战与突破
  • 《ZLToolKit源码学习笔记》(1)VS2019编译实战:从CMake配置到调试运行
  • 5款3D轻量化工具一键帮你解决卡顿问题
  • Windows窗口尺寸精准调控工具:WindowResizer深度解析与实战指南
  • BRAINFUSENET:基于多模态融合与边缘计算的轻量化癫痫发作检测系统
  • 关于QLineEdit自定义范围
  • 14. WDG看门狗
  • 融合位置嵌入的视觉Transformer在北极地貌遥感检测中的应用
  • 华硕笔记本性能控制新选择:GHelper轻量化解决方案深度解析
  • KLayout完整指南:开源IC版图工具快速上手与专业应用
  • 阴阳师自动化脚本完整指南:解放双手的智能游戏管家
  • 【Android】语燕输入法-无广纯净-输入快人一步-轻量纯净的高效输入之选