51nod1042(0-x出现次数&分治)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042

 

题意:中文题诶~

 

思路:这道题和前面的51nod1009好像,直接套用那个算法也是能ac的,不过我还是喜欢换个口味;

求a, b之间个数字出现的次数。可以由分治的思想,先求出他们在0~b出现的次数, 再求出在0~a-1出现的次数,前者减去后者即为答案;

然而如何求出0~x各个数字出现的次数我是看了一本书上的方法才会的,这里直接给出代码好了,随便带入一组数据也不难验证其正确性,所以也就不多说啦。。。

 

代码:

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 #define MAXN 10
 4 using namespace std;
 5 
 6 ll value=1;  //***value记录当前的权值
 7 ll vis[MAXN];  //***vis[i]存储0到x中i出现的次数
 8 
 9 void deal(ll n){
10     if(n<=0){
11         return;
12     }
13     ll one=n%10;  //***one, ten分别表示当前n的个位和高位
14     n/=10;
15     ll ten=n;
16     for(int i=0; i<=one; i++){  //***累计当前个位出现的次数
17         vis[i]+=value;
18     }
19     while(ten){
20         vis[ten%10]+=(one+1)*value;  //***累计当前高位出现的次数
21         ten/=10;
22     }
23     for(int i=0; i<10; i++){  //***累计权值范围数出现的次数
24         vis[i]+=n*value;  //***注意这里会累加到0开头的情况
25     }
26     vis[0]-=value;   //***将第一位是0的情况排除
27     value*=10;
28     deal(n-1);
29 }
30 
31 int main(void){
32     ll a, b;
33     cin >> a >> b;
34     if(a>b){
35         swap(a, b);
36     }
37     deal(b);
38     value=-1;
39     deal(a-1);
40     for(int i=0; i<10; i++){
41         cout << vis[i] << endl;
42     }
43     return 0;
44 }

 

还是写一下套用1009ac的代码好了~

 

代码:

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 ll deal(ll n, ll key){
 6     ll x=n, cnt=1, ans=0;
 7     while(n){
 8         if(!key){
 9             ans-=cnt;
10         }
11         ll gg=n%10;
12         ll num=x/(cnt*10);
13         if(gg<key){
14             ans+=num*cnt;
15         }else if(gg==key){
16             ans+=num*cnt+x%cnt+1;
17         }else{
18             ans+=(num+1)*cnt;
19         }
20         cnt*=10;
21         n/=10;
22     }
23     return ans;
24 }
25 
26 int main(void){
27     ll a, b;
28     cin >> a >> b;
29     if(a>b){
30         swap(a, b);
31     }
32     for(ll i=0; i<10; i++){
33         cout << deal(b, i)-deal(a-1, i) << endl;
34     }
35     return 0;
36 }

 

转载于:https://www.cnblogs.com/geloutingyu/p/6284198.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值