数位dp
有这么一道板子
题目描述
给定两个正整数 aa 和 bb,求在 [a,b][a,b] 中的所有整数中,每个数码 (digit) 各出现了多少次。
输入格式
输入文件中仅包含一行两个整数 aa、bb,含义如上所述。
输出格式
输出文件中包含一行 1010 个整数,分别表示 0−90−9 在 [a,b][a,b] 中出现了多少次。
可以记忆化搜索,
如图hzwer的一样,
裸的数位dp
大概只有我这种逗比不会做
递推出f[i][j][k]表示长度为i开头j的所有数字中k的个数
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstring> 7 #define ll long long 8 using namespace std; 9 inline ll read() 10 { 11 ll x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct data{ll a[10];}; 17 ll a,b,t[25]; 18 data f[25][10]; 19 data operator+(data a,data b) 20 { 21 data t; 22 for(int k=0;k<=9;k++) 23 t.a[k]=a.a[k]+b.a[k]; 24 return t; 25 } 26 data cal(ll x) 27 { 28 data ans;for(int i=0;i<=9;i++)ans.a[i]=0; 29 if(!x) 30 { 31 ans.a[0]=1; 32 return ans; 33 } 34 int len=15; 35 while(t[len]>x)len--; 36 for(int i=1;i<len;i++) 37 for(int j=1;j<=9;j++) 38 ans=ans+f[i][j]; 39 ans.a[0]++; 40 int cur=x/t[len]; 41 for(int i=1;i<cur;i++) 42 ans=ans+f[len][i]; 43 x%=t[len]; 44 ans.a[cur]+=x+1; 45 for(int i=len-1;i;i--) 46 { 47 cur=x/t[i]; 48 for(int j=0;j<cur;j++) 49 ans=ans+f[i][j]; 50 x%=t[i]; 51 ans.a[cur]+=x+1; 52 } 53 return ans; 54 } 55 int main() 56 { 57 t[1]=1;for(int i=2;i<=15;i++)t[i]=t[i-1]*10; 58 for(int i=0;i<=9;i++)f[1][i].a[i]=1; 59 for(int i=2;i<=12;i++) 60 for(int x=0;x<=9;x++) 61 for(int y=0;y<=9;y++) 62 { 63 f[i][y]=f[i][y]+f[i-1][x]; 64 f[i][y].a[y]+=t[i-1]; 65 } 66 a=read();b=read(); 67 data t1=cal(b),t2=cal(a-1); 68 for(int i=0;i<=9;i++) 69 { 70 printf("%lld",t1.a[i]-t2.a[i]); 71 if(i!=9)printf(" "); 72 } 73 return 0; 74 }
我还能搜索
#include <cstdio> #include <iostream> #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define ls (t<<1) #define rs ((t<<1)|1) #define mid ((l+r)>>1) #define mk make_pair #define pb push_back #define fi first #define se second ll p[20]; ll ans[11]={}; void chushi() { p[0]=1; for (int i=1;i<18;i++) { p[i]=p[i-1]*10; } //用于取某一位数 } void dfs(ll x,int f) { //x为终点 if (x==-1) { ans[0]++; return; } for (int k=1;k<10;k++) { for (int i=1;i;i++) { //取现在位数 ll l=x/p[i]; ll r=x%p[i-1]; ll now=x%p[i]/p[i-1]; if (now>k) { ans[k]+=(l+1)*p[i-1]*f; } else if(now==k) { ans[k]+=(l*p[i-1]+r+1)*f; } else ans[k]+=l*p[i-1]*f; if (p[i]>x) break; } } for (int i=1;i;i++) { //单独处理0 ll l=x/p[i]; ll r=x%p[i-1]; ll now=x%p[i]/p[i-1]; if (now>0) ans[0]+=l*p[i-1]*f; else ans[0]+=((l-1)*p[i-1]+r+1)*f; if (p[i]>x) break; } } ll n,m; int main() { cin>>n>>m; chushi(); dfs(m,1); dfs(n-1,-1); for (int i=0;i<=9;i++) { cout<<ans[i]<<" "; if (i==9) cout<<endl; } return 0; }
还需好好理解理解