[ZJOI2010]数字计数 题解
2024-10-06 21:17:13
这道题是一道数位DP的模板题;
因为窝太蒟蒻了,所以不会递推,只会记忆化搜索;
首先,咋暴力咋来;
将一个数分解成一个数组,这样以后方便调用;
数位DP的技巧:(用1~b的答案)-(1~a的答案)就是(a~b的答案);
那么对于每个数码i,我们做两次dfs(分别以a为上界和以b为上界);
设正在搜索的数码是digit:
枚举每一位,当这位==digit时,便将答案+1,并记忆化;
然后就没了;
可是这样做忽略了两个重要的事情:
1.可能存在前导零;
2.目前搜到的数比目标值要大;
对于这两件事,在dfs中记录limit=1表示改为的上界就是目标的这一位的上界,否则对这一位不作要求;
head=1表示目前搜到的数不存在前导零;
很显然的:(伪代码)
long long dfs(int pos,int limit,int lead,int digit,long long sum) register int up=; //up表示这一位的上界 if(limit) up=num[pos]; inc(j,,up) ans+=dfs(pos-,(j==up)&&limit,lead||j,digit,sum+((j||lead)&&(j==digit)));
利用好位运算,然后注意要记忆化,然后就可以AC了;
#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
long long a,b,f[34][3400],num[34];
long long dfs(int pos,int limit,int lead,int digit,long long sum)
{
long long ans=0;
if(pos<=0) return sum;
if(!limit&&lead&&f[pos][sum]!=-1) return f[pos][sum];
register int up=9; if(limit) up=num[pos];
inc(j,0,up) ans+=dfs(pos-1,(j==up)&&limit,lead||j,digit,sum+((j||lead)&&(j==digit)));
if(!limit&&lead) f[pos][sum]=ans;
return ans;
}
long long work(long long x,register int type)
{
memset(f,-1,sizeof(f));
register int len=0;
while(x){
num[++len]=x%10;
x/=10;
}
return dfs(len,1,0,type,0);
}
int main()
{
cin>>a>>b;
for(register int i=0;i<=9;i++){
cout<<work(b,i)-work(a-1,i);
if(i!=9) cout<<" ";
}
}
/*
1 99
*/
最新文章
- 快速排序中的partition函数的枢纽元选择,代码细节,以及其标准实现
- Lambda表达式详解
- 本机tomcat的server.xml被还原的问题及解决办法
- [转]CSS编码规范
- 超快的 FastText
- cf 383 D
- ORA-25153: Temporary Tablespace is Empty解决方法
- c++游戏编程书籍
- cannot locate symbol ";atof"; referenced by错误分析
- 浅析Spring MVC工作机制
- 201421123042 《Java程序设计》第5周学习总结
- MIP 内容声明
- easyUI的常见属性
- python迭代和解析(3):range、map、zip、filter和reduce函数
- MySQL JDBC驱动版本与MySQL数据库版本对应关系
- docker-mysql-cron-backup不能执行任务
- stylus笔记(三)
- Codefroces 958C2 - Encryption (medium)
- FastReport 打印模版页(TFrxReportpage)复制
- js截取相应的域名----正则匹配法 和校验Url 正则表达式