算法实现题 1-1 统计数字问题

问题描述:

一本书的页码从自然数 1 开始顺序编码直到自然数 n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字 0。例如,第 6 页用数字 6 表示,而不是 06 或 006 等。数字计数问题要求对给定书的总页码 n,计算出书的全部页码中分别用到多少次数字 0,1,2,…,9。

编程任务:

给定表示书的总页码的 10 进制整数 n (1≤n≤109) 。编程计算书的全部页码中分别用到多少次数字 0,1,2,…,9。

数据输入:

输入数据由文件名为 input.txt 的文本文件提供。每个文件只有 1 行,给出表示书的总页码的整数 n。

结果输出:

程序运行结束时,将计算结果输出到文件 output.txt 中。输出文件共有 10 行,在第 k 行输出页码中用到数字 k-1 的次数,k=1,2,…,10。

输入文件示例

input.txt
11

输出文件示例

output.txt
1
4
1
1
1
1
1
1
1
1

思路:

  1. 求数n的位数
    int count = (int)log10(num)+1; //求位数
  2. 划分区间 (high middle low)并加和
    (每次就算一位,为了计算方便,加上前导0,最后再去掉)
  3. 去掉前导0

以 4598 为例

  1. len=4
  2. 循环 每位数 计算该位 出现多少 0-9
    high middle low
    459 8 0
    45 9 8
    4 5 98
    0 4 598
    第一行 个位中
    0-7出现的次数 (459+1)×1
    8 出现的次数 459×1+0+1
    9 出现的次数 459×1
    第二行 十位中
    0-8 出现的次数 (45+1)×10
    9 出现的次数 45×10+8+1
    第三行 百位中
    0-4 出现的次数 (4+1)×100
    5 出现的次数 4×100+98+1
    6-9 出现的次数 4×100
    第四行 千位中
    0-3 出现的次数 (0+1)×1000
    4 出现 的次数 0×1000+598+1
    5-9 出现的次数 0 ×1000
  3. 去掉前导0
    0000-0009 0010 -0099 0100-0999 1000-----
    个位 多算 1 个0
    十位 多算 10 个0
    百位 多算 100 个0
    千位 多算 1000 个0

代码:

#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

class File    //一个文件类,从文件中读取文件,输入和输出,并比较运行是否正确
{
public :
    int getNum (string path)
    {
        FILE *f=fopen(path.c_str(),"r");
        int num;
        fscanf(f,"%d",&num);
        fclose(f);
        return num;
    }
    vector<int> answer(string path)
    {
        FILE *f=fopen(path.c_str(),"r");
        vector<int> ve;
        int num;
        while(fscanf(f,"%d",&num)!=EOF)
        {
            ve.push_back(num);
        }
        fclose(f);
        return ve;
    }
    bool compare(vector<int>ve,int a[],int N)
    {
        for(int i=0;i<N;i++)
        {
            if(a[i]!=ve[i])
                return false;
        }
        return true;
    }
};

int main()
{
    File f;
    bool temp=true;
    for(int k=0; k<10; k++)
    {
        int num=f.getNum("F:\\算法\\实验1-素材-算法\\test\\count"+to_string(k)+".in");
        int count = (int)log10(num)+1; //求位数
        int high,middle,low;
        int a[10]= {0};
        for(int i=0; i<count; i++)
        {
            high=num/(int)pow(10,i+1);
            low=num%(int)pow(10,i);
            middle =num/(int)pow(10,i)%10;
            for(int j=0; j<middle; j++)
            {
                a[j]+=(high+1)*(int)pow(10,i);
            }
            a[middle]+=high*(int)pow(10,i)+low+1;
            for(int j=middle+1; j<10; j++)
            {
                a[j]+=high*(int)pow(10,i);
            }
        }
        for(int i=0; i<count; i++)
            a[0]-=(int)pow(10,i);

        vector<int> ve;
        ve=f.answer("F:\\算法\\实验1-素材-算法\\answer\\count"+to_string(k)+".out");
        bool flag=true;
        flag=f.compare(ve,a,10);
        if(!flag)
        {
            cout << "第" << k << "个测试用例未通过" << endl;
            temp=false;
        }
        ve.clear();
    }
    if(temp)
        cout << "测试用例全部通过!" << endl;

    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值