UVA - 1640 The Counting Problem (数位dp)
题意:统计l-r中每种数字出现的次数
很明显的数位dp问题,虽然有更简洁的做法但某人已经习惯了数位dp的风格所以还是选择扬长避短吧(说白了就是菜啊)
从高位向低位走,设状态(u,lim,ze)表示当前走到了第几位,是否有上限,是否有前导零的状态,则问题转化成了求所有转移路径中经过的所有数字的数量统计问题。
设f[u][lim][ze]为从状态(u,lim,ze)向后走能到达的状态总数,g[u][lim][ze][i]为状态(u,lim,ze)及其向后走能到达的所有状态中数字i出现的总数,各种转移就行了,实现细节比较复杂就不啰嗦了~~
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=10+5,inf=0x3f3f3f3f; 5 int l,r,bit[N],nb,f[N][2][2],g[N][2][2][10],vis[N][2][2],cnt[N],ka; 6 void dfs(int u,int lim,int ze) { 7 if(vis[u][lim][ze]==ka)return; 8 vis[u][lim][ze]=ka; 9 if(u==0) { 10 f[u][lim][ze]=1; 11 for(int i=0; i<=9; ++i)g[u][lim][ze][i]=0; 12 return; 13 } 14 f[u][lim][ze]=0; 15 for(int i=0; i<=9; ++i)g[u][lim][ze][i]=0; 16 for(int i=0; i<=(lim?bit[u]:9); ++i) { 17 int lim2=(lim&&i==bit[u]),ze2=(ze&&i==0); 18 dfs(u-1,lim2,ze2); 19 f[u][lim][ze]+=f[u-1][lim2][ze2]; 20 if(!(ze&&i==0))g[u][lim][ze][i]+=f[u-1][lim2][ze2]; 21 for(int j=0; j<=9; ++j)g[u][lim][ze][j]+=g[u-1][lim2][ze2][j]; 22 } 23 } 24 void solve(int x,int F) { 25 for(nb=0; x; x/=10)bit[++nb]=x%10; 26 dfs(nb,1,1); 27 for(int i=0; i<=9; ++i)cnt[i]+=F*g[nb][1][1][i]; 28 } 29 int main() { 30 while(scanf("%d%d",&l,&r)&&l) { 31 if(l>r)swap(l,r); 32 memset(cnt,0,sizeof cnt); 33 ++ka,solve(r,1); 34 ++ka,solve(l-1,-1); 35 for(int i=0; i<=9; ++i)printf("%d%c",cnt[i]," \n"[i==9]); 36 } 37 return 0; 38 }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法