1042 数字0-9的数量(非数位dp解法)

1042 数字0-9的数量

 
给出一段区间a-b,统计这个区间内0-9出现的次数。
 
比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
 

输入

两个数a,b(1 <= a <= b <= 10^18)

输出

输出共10行,分别是0-9出现的次数

输入样例

10 19

输出样例

1
11
1
1
1
1
1
1
1
1


题意很明确,
其实只要能求的到b的就可以.
然后用val(b) - val(a-1)就能得出结果

我的思路是既然要求1到n的,那么每次我只计算1到n的每个数的最后一位.
并且记录最后一位的状态变化.
比如求2018
那么第一次就是2018/10 = 201 2018%10 = 8
那么从0到9每个位上就能加201, 然后 1到8都加1
下一次就是201/10 = 20 201%10 = 1
那么0到9每位加20*10 ,然后从1加9;
仔细看代码就知道我的思路是什么了.

每次都减掉最后一位数.
 1 #include <bits/stdc++.h>
 2 #define ll long long int
 3 using namespace std;
 4 ll a,b;
 5 ll an[10], bn[10];
 6 void solve(ll x,ll xn[]){
 7     ll ans = 1;
 8     ll cnt = 0;
 9     while(x){
10         ll aa = x/10;
11         for(int i = 0; i <= 9; i++){
12             if(i == 0 && x%10 == 0)
13                 xn[i] += (aa - 1)*ans;
14             else
15                 xn[i] += aa*ans;
16         }
17         ll bb = x%10;
18         for(int i = 1; i < bb; i++){
19             xn[i] += ans;
20         }
21         xn[bb] += cnt + 1;
22         cnt = cnt + (x%10 )*ans;
23         ans *= 10;
24         x /= 10;
25     }
26 }
27 int main(){
28     scanf("%lld%lld", &a,&b);
29     solve(b, bn);
30     solve(a - 1, an);
31     for(int i = 0; i <= 9; ++i){
32         printf("%lld\n",bn[i] - an[i]);
33     }
34     return 0;
35 }

 

 

 

数位dp

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #define LL long long
 7 using namespace std;
 8 //循环两遍,sumright-sumleft
 9 //10132 
10 //==0:pre*after     !=0:cur*pre*对应位数+after
11 //0 + 132 + 10*cur*100+after + 101*cur*100*10+2 +1013*1
12 //19 1*
13 LL ans[10];
14 void solve(LL n,bool f)
15 {
16     LL cur,pre,after,temp=1,sign=f?1:-1;
17     int cnt = 0;
18     while((n/temp)!=0)
19     {
20         cur = (n/temp)%10;
21         pre = (n/(temp*10));
22         after = n - (n/temp)*temp;
23         //cout<<pre<<' '<<cur<<' '<<after<<endl;
24         int tmp = after,mul=1;
25         while(tmp){mul*=10;tmp/=10;}
26         //cout<<" m is "<<mul<<endl;
27         for(int i=0;i<10;i++)
28         {
29             if(cur>i) ans[i]+=(pre+1)*temp*sign;
30             if(cur<i) ans[i]+=pre*temp*sign;
31             if(cur==i) ans[i]+=(pre*temp+after+1)*sign;
32         }
33         ans[0]-=temp*sign;
34         temp*=10;
35     }
36 }
37 //10+1+1
38 int main()
39 {
40     LL l,r;
41     bool f;
42     cin>>l>>r;
43     f = false;
44     solve(l-1,f);
45     f = true;
46     solve(r,f);
47     for(int i=0;i<10;i++)
48     {
49         cout<<ans[i]<<endl;
50     }
51     return 0;
52 }

 

 

转载于:https://www.cnblogs.com/zllwxm123/p/9941998.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值