题意:
求[l,r]中数字0-9分别出现的次数,11算两次1
思路:
数位dp题解好难写,直接贴代码吧
dp[i]表示[0, 10^i-1]中出现j的次数(按i位补全前导0,显然0-9出现的次数是相同的)
最后再减去每一位出现的前导零即可
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef long long LL; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 998244353; const int maxn = 2e5+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); ll n; ll dp[maxn]; ll po[maxn]; vector<ll> sv(ll n){ ll len = 0; vector<ll>ans(10); for(int i = 0; i < 10; i++)ans[i] = 0; ll tmp = 0; ll x = n; while(n){ ll d = n%10; n/=10; len++; for(int i = 0; i < 10; i++){ if(d > i){ ans[i] += po[len-1] + d*dp[len-1]; } else if(d==i){ ans[i] += d*dp[len-1]+tmp+1; } else{ ans[i] += d*dp[len-1]; } } tmp += d*po[len-1]; } ll m = 1; while(x){ ans[0]-=m; m*=10; x/=10; } return ans; } int main() { //dp[0] = 0; ll tmp = 1; po[0] = 1; for(int i = 1; i <= 18; i++){ po[i] = 10*po[i-1]; dp[i] = dp[i-1]*10 + po[i-1]; } ll l, r; scanf("%lld %lld", &l,&r); //scanf("%lld",&r); vector<ll>v1(10),v2(10); v1=sv(l-1); v2=sv(r); for(int i = 0; i < 10; i++){ printf("%lld\n",v2[i]-v1[i]); } return 0; } /* 15542 */
原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10519565.html
时间: 2024-11-05 17:33:43