再次计数问题

题目大意:

给定你一个区间,要求你统计在这个区间中,每个数字位[0,9]出现的次数。

题目测试数据与数据范围:

23 123
20 44 21 21 20 20 20 20 20 20
223 1232314
712619 1055929 755323 714950 712620 712619 712619 712619 712619 712619
343 23235
8879 19879 13051 9069 8877 8880 8879 8879 8879 8879
1 2
0 1 1 0 0 0 0 0 0 0
0 0

数的范围可能比较大 a,b (0,10^9).

题目分折:

如果直接进行枚举输出,你一定会超时的,看来得有更好的解决方案。如果把一个数字的每一位分而治之,采用合理的正确的分治手段,我们一定能够达到目标。如果先处理个位,那如何才能取完所在的个位,而直接可以去统计它的更高位,我们以下面这个例子说明我们的方法。最大数为 197 。

1   2   3   4   5   6   7   8   9  10
  11  12  13  14  15  16  17  18  19  20
  21  22  23  24  25  26  27  28  29  30
  31  32  33  34  35  36  37  38  39  40
  41  42  43  44  45  46  47  48  49  50
  51  52  53  54  55  56  57  58  59  60
  61  62  63  64  65  66  67  68  69  70
  71  72  73  74  75  76  77  78  79  80
  81  82  83  84  85  86  87  88  89  90
  91  92  93  94  95  96  97  98  99 100
 101 102 103 104 105 106 107 108 109 110
 111 112 113 114 115 116 117 118 119 120
 121 122 123 124 125 126 127 128 129 130
 131 132 133 134 135 136 137 138 139 140
 141 142 143 144 145 146 147 148 149 150
 151 152 153 154 155 156 157 158 159 160
 161 162 163 164 165 166 167 168 169 170
 171 172 173 174 175 176 177 178 179 180
 181 182 183 184 185 186 187 188 189 190
 191 192 193 194 195 196 197

那么对于190-197 的数它的每一个(所有位)都可以统计出来。再来对 0-189 这些数的每个个位数都可以统计出来,那么剩下的就会成了这样的一个图(还清注意,留意一下 0 的变化有所不同,主要原因是因为我们已经处理了一次,不能再重复)。

                         1
  1  1  1  1  1  1  1  1  1  2
  2  2  2  2  2  2  2  2  2  3
  3  3  3  3  3  3  3  3  3  4
  4  4  4  4  4  4  4  4  4  5
  5  5  5  5  5  5  5  5  5  6
  6  6  6  6  6  6  6  6  6  7
  7  7  7  7  7  7  7  7  7  8
  8  8  8  8  8  8  8  8  8  9
  9  9  9  9  9  9  9  9  9 10
 10 10 10 10 10 10 10 10 10 11
 11 11 11 11 11 11 11 11 11 12
 12 12 12 12 12 12 12 12 12 13
 13 13 13 13 13 13 13 13 13 14
 14 14 14 14 14 14 14 14 14 15
 15 15 15 15 15 15 15 15 15 16
 16 16 16 16 16 16 16 16 16 17
 17 17 17 17 17 17 17 17 17 18
 18 18 18 18 18 18 18 18 18

其实就是每个数字有 10 个,这也是我们为什么等下要扩大 10 倍的原因。我们看到它变成了如下的一个问题。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

如是我们可以用相同的方法处理这个问题,难道不是吗? 把 10 到 18 的先处理,然后再处理 1-9 的个位,注意这里的统计量是要乘十的,相信原理你们会明白,上面的清楚。那么最后的问题就是 1 1 1 1 1 1 1 1,它等价于 1,只不过这个 1 是以百倍为计量。所以对于这个问题,我们的编程方法思路就是对给定的两个数,分别求出它们各自从 0 到本身每个 数出现的个数,相减即可。

小乐一下:

对于我们看待问题,要从多个方面去考虑问题,而且要有自己的思想,不能直接复制别人的,只有经过自己思考,花点时间自己思考,不要害怕花时间,因为这与你直接拿别人的代码敲一遍,有很大的差距,你懂得。自己的才是最好的。

我的代码,更好更简洁的由你来实现,不要直接自制。

#include<stdio.h>

int dp[10],values;

void account(int a){
    int i,j;
    if(a<=0) return;
    int one = a % 10;
    int ten = a/10;
    a /= 10;
    for(i = 0;i<=one;i++) dp[i] += values;
    while(ten){
        dp[ten%10] += (one + 1)* values;
        ten/=10;
    }
    for(i = 0;i<=9;i++) dp[i] += a * values;
    dp[0] -= values ;
    values *= 10;
    account(a-1);
}

int main(){
    int a,b;
    int i;
    while(scanf("%d%d",&a,&b)!=EOF,a+b){
        int temp;
        if(a<b){temp = a;a = b;b = temp;}
        for(i = 0;i<10;i++) dp[i] = 0;
        values = 1;
        account(a);
        values = -1;
        account(b-1);
        for(i = 0;i<9;i++) printf("%d ",dp[i]);
        printf("%d\n",dp[9]);
    }
    return 0;
}

伟大的梦想成就伟大的人,从细节做好,从点点滴滴做好,从认真做好。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个Verilog代码示例,实现了一个影子寄存器,并且在影子寄存器中的数字更新时,计数寄存器从零开始计数;而当影子寄存器的数值不变时,计数寄存器会计数到影子寄存器当前保存的值,然后清零重新计数: ```verilog module ShadowAndCountRegister( input wire clk, // 时钟信号 input wire reset, // 复位信号 input wire data_in, // 输入数据信号 output reg data_out, // 输出数据信号 output reg [7:0] count // 计数寄存器 ); reg shadow_reg; // 影子寄存器 reg [7:0] max_count; // 最大计数值 always @(posedge clk or posedge reset) begin if (reset) begin shadow_reg <= 1'b0; // 复位影子寄存器 count <= 8'b0; // 复位计数寄存器 max_count <= 8'b0; // 复位最大计数值 end else begin if (data_in != shadow_reg) begin shadow_reg <= data_in; // 当影子寄存器中的数字更新时,更新影子寄存器 count <= 8'b0; // 重置计数寄存器为零 max_count <= data_in; // 更新最大计数值为新的影子寄存器值 end else if (count < max_count) begin count <= count + 1; // 影子寄存器数值不变时,计数寄存器递增 end else begin count <= 8'b0; // 计数寄存器计数到最大值后清零 max_count <= shadow_reg; // 清零后更新最大计数值为当前影子寄存器值 end end end always @(posedge clk) begin if (data_in != shadow_reg) begin data_out <= data_in; // 当输入数据发生变化时,更新输出数据 end end endmodule ``` 在上述代码中,我们使用一个单比特的影子寄存器 `shadow_reg` 来保存上一个时钟周期的寄存器值,并使用一个8位的计数寄存器 `count` 来记录递增的次数。我们还使用一个8位的最大计数值 `max_count` 来记录影子寄存器的当前保存值。 当输入数据发生变化时,我们更新影子寄存器的值,并将计数寄存器重置为零。当影子寄存器的值不变时,计数寄存器会递增,直到达到最大计数值。一旦计数寄存器达到最大计数值,我们将计数寄存器清零,并更新最大计数值为当前影子寄存器的值。 请注意,上述代码仅提供了一个基本示例,您可能需要根据具体情况进行修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值