P2602 [ZJOI2010] 数字计数 题解
数位dp的板子题?
显然
考虑
所以我们可以预处理出
实际操作的时候,我们可以不用写两维,写一维的cnt数组记录一下就可以。
再加上限制,当前数的方案数我们由小于等于它的最大999……9和剩余部分拼成。后面这一部分就是各位数字上的数乘
加上比当前位小的数多出现了
#include<bits/stdc++.h>
using namespace std;
long long a,b,l,r,num;
int numa[15],numb[15];
long long cnt[11];
long long f[15];
long long po[15]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,100000000000,};
int main(){
for(int i=1;i<=15;++i) f[i]=i*po[i-1];
scanf("%lld %lld",&a,&b);
if(a>b) swap(a,b);
--a;
while(a) numa[++l]=a%10,a/=10;
while(b) numb[++r]=b%10,b/=10;
for(int i=l;i>=1;--i){
for(int j=0;j<=9;++j) cnt[j]-=numa[i]*f[i-1];
for(int j=0;j<numa[i];++j) cnt[j]-=po[i-1];
num=0;
for(int j=i-1;j>=1;--j) num=num*10+numa[j];
cnt[numa[i]]-=(num+1);
cnt[0]+=po[i-1];
}
for(int i=r;i>=1;--i){
for(int j=0;j<=9;++j) cnt[j]+=numb[i]*f[i-1];
for(int j=0;j<numb[i];++j) cnt[j]+=po[i-1];
num=0;
for(int j=i-1;j>=1;--j) num=num*10+numb[j];
cnt[numb[i]]+=(num+1);
cnt[0]-=po[i-1];
}
for(int i=0;i<=9;++i) printf("%lld ",cnt[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现