统计1到n之间的所有数字中1出现的个数

统计1到n之间的所有数字中1出现的个数

实现函数int func(unsigned n),其中n为正整数,返回从1到n(包含1和n)之间出现的1的个数,如

func(13)=6,func(9)=1。(注意:不能将整数转化为字符串)

这是网上以为兄弟的分析:

分析:

对于数n,可以把它分成三段,高位段most,当前位cur,低位段least,每一段分别为一个整数。对于一个有digit位的数,假设当前位是左数第i位,则设一个临时变量tmp为10的digit-i次方,即比least多一位的最小整数。如数123456,为6位数,digit=6,设当前为左起第3位,则i=3,most=12,cur=3,

least=456,tmp=1000。

如果当前位大于1,则从1到n间出现在当前位出现的1的个数是most*tmp+tmp;如果等于1,则是

most*tmp+least+1;如果小于,则为most*tmp。

实现:

int func(unsigned n)
{
    int count = 0;
    int digit = (int)log10(n) + 1;
    int most, cur, least, tmp;
    int i;

    for (i=0; i<digit; ++i)
    {
        tmp = (int)pow(10, digit-i-1);
        most = n / tmp / 10;
        cur = (n / tmp) % 10;
        least = n % tmp;
        count += most * tmp;
        if (cur > 1)
        {
            count += tmp;
        }
        else if (cur == 1)
        {
            count += least + 1;
        }
    }
    return count;
}

我从新解释一下,思想都差不多:

对于一个数字中的任何第k位出现1的次数,我们将之分为两个阶段:

1. 其高位(>k的那些为,k从低位开始计数)有多大的概率使得k位出现1

2. 每次第k为出现1之后,这个1能保持多长时间。

举个例子:

n=3243,k=2,即十位上的那个数字m[k]=4

1. 显然,十位上出现1的次数是 n%100,即:如果我让十位上固定是1,然后百位和千位上数字从0增长可以增长到多少?显然,增长到32,所以,高位能使得k=2的位置上出现n%100次1,请注意:还有一次是要根据m[k]来确定的;如果m[k]>=1,则是n%100+1,否则就是n%100了。而第二位是对100mod,也就是第k位就是pow(10,k) mod n

2. 一旦第二位出现了1,能保持多长时间呢?显然,如果十位是1,那么10,11,12,。。。,19都能保持住,能保持10次。wait,是不是总是如此,不是的,如果本来第二位是大于1,当然没有问题,比如25,这个时候,10到19都小于25,所以没有问题,十位上的1出现10次;但是如果十位上是1,比如17,这样就不能出现10次了;只能出现10,11,。。。。17,也就是8次。

基于此,给出代码实现:

int func1(unsigned int n)
{
    int count = 0;
    int len = (int)log10((double)n);//总共多少位
    int lenL = -1, lenM = -1, lenR = -1;
    int idxD = -1;
    while( len != -1 )
    {
        lenM = (int)pow(10,(double)len+1);
        lenR = (int)pow(10,(double)len);
        idxD = n%lenM/lenR;//高位能让该位出现几次1
        count += ( n / lenM ) * lenR;
        if( idxD == 1 )//当前位置上是1,要小心
            count += n % lenR + 1;
        else if( idxD > 1 )//大于1,直接加
            count += lenR;
        len--;
    }
    return count;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值