洛谷 P1239 计数器
题目描述
一本书的页数为N,页码从1开始编起,请你求出全部页码中,用了多少个0,1,2,…,9。其中—个页码不含多余的0,如N=1234时第5页不是0005,只是5。
输入输出格式
输入格式:
一个正整数N(N≤10^9),表示总的页码。
输出格式:
共十行:第k行为数字k-1的个数。
输入输出样例
输入样例#1: 复制
11
输出样例#1: 复制
80分的暴力
1
4
1
1
1
1
1
1
1
1
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n; int num[10]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ int x=i; while(x){ num[x%10]++; x/=10; } } for(int i=0;i<=9;i++) cout<<num[i]<<endl; }
正解思路:数位DP
f[i][j][k]表示有i位,最高位为j,数字k出现的次数。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,tot; int ans[10]; int sum[16],num[10]; int f[11][10][11]; int main(){ scanf("%d",&n); for(int i=0;i<=9;i++) f[1][i][i]=1; sum[1]=1; for(int i=2;i<=10;i++){ sum[i]=sum[i-1]*10; f[i][0][0]=f[i-1][1][0]*9+f[i-1][0][0]+sum[i]; for(int j=1;j<=9;j++) f[i][0][j]=f[i-1][0][j]*9+f[i-1][j][j]; for(int j=1;j<=9;j++){ f[i][j][0]=f[i-1][1][0]*9+f[i-1][0][0]; for(int k=1;k<=9;k++){ if(j==k) f[i][j][k]=f[i-1][0][k]*9+f[i-1][k][k]+sum[i]; else f[i][j][k]=f[i-1][0][k]*9+f[i-1][k][k]; } } } int x=n; while(x){ num[++tot]=x%10;x/=10; } for(int i=1;i<tot;i++) for(int j=1;j<=9;j++) for(int k=0;k<=9;k++) ans[k]+=f[i][j][k]; for(int i=tot;i>=1;i--){ for(int j=0;j<num[i];j++){ if(i==tot&&j==0) continue; for(int k=0;k<=9;k++) ans[k]+=f[i][j][k]; } ans[num[i]]+=n%sum[i]+1; } for(int i=0;i<=9;i++) printf("%d\n",ans[i]); }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。