AT_dp_s 题解

题目传送门

第一道数位 dp,检验一下自己懂没懂。

特别感谢 yinhee 大佬,他的讲解令我受益匪浅。

1|0题目分析

dppos,res,lim 为当前枚举到从高位往低位数第 pos 位,数字和取模后的余数为 res 时的方案数,其中 lim 可以理解为一个布尔值,0 表示没有到上限,1 表示到了上限。

然后是一个数位 dp 的板子,我特别讲一下这一行代码:

tot+=dfs(pos-1,(res+i)%d,(lim!=0)&&(i==maxx));

其中 maxx 是当前枚举位可选的最大值。

这里就是在枚举第 pos1 位,选择了 i 作为这位的数,res+i 就是新的数字和。而后面的判断条件就是在看枚举到目前为止,该数是否还与 k 的前缀相同,是就说明到目前为止还是最大的,否则就不是。

2|0贴上代码

#include<bits/stdc++.h> // #define int long long #define ok printf("1") #define no printf("0") using namespace std; int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-48; c=getchar(); } return x*f; } const int mod=1e9+7; const int maxn=10010; const int maxm=110; int n,d; int a[maxn]; int dp[maxn][maxm][2]; string s; int dfs(int pos,int res,int lim){ if(pos==0){ if(res==0) return 1; else return 0; } if(dp[pos][res][lim]!=-1) return dp[pos][res][lim]; int maxx=9,tot=0; if(lim!=0) maxx=a[pos]; for(register int i=0;i<=maxx;++i){ tot+=dfs(pos-1,(res+i)%d,(lim!=0)&&(i==maxx));tot%=mod; } dp[pos][res][lim]=tot; return tot; } inline void init(){ cin>>s;n=s.size(); cin>>d; for(register int i=0;i<n;++i) a[n-i]=s[i]-48; memset(dp,-1,sizeof(dp)); } int main(){ init(); printf("%d",(dfs(n,0,1)-1+mod)%mod); }

__EOF__

本文作者yizhixiaoyun
本文链接https://www.cnblogs.com/yizhixiaoyun/p/17405449.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   yizhixiaoyun  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
点击右上角即可分享
微信分享提示