zoukankan      html  css  js  c++  java
  • 51nod 1009 数字1的数量

    题目来源:51nod1009

    题目大意:输入一个十进制数N,计算出从0到N所有数里所有1的个数(注:111里有3个1)

    【冷静分析】这道题乍一看有些棘手(实际也不是水题),我们不妨先找找规律。

    ·一位数里一共有几个1?

    答:1。一个。

    ·两位数里有几个1?

    答:个位数是1的:1,11,21,31,……(10个)

    十位数是1的:10,11,12,13……(10个)

    所以有二十个。

    ·三位数呢?

    答:我不想列举了,有三百个。

    等等:1,20,300……

    ……??????!似乎真的有规律啊!

    也就是说,从0——9999(k个9)一共有1的个数是:

    f(k)=k(10^k)————①*

    惊人的发现啊!我们继续找规律。

    不妨以12345这个数为例:

    由结论①可知,在1——9999内有4000个1

    接下来看10000——12345

    我们惊奇地发现,这2346个数的万位都是1,所以答案加上2346

    顺着这个思路,我们再来看千位:

    当千位为0时,后面的三个数无论是多少,整体都不会超过12345

    我们自然想到结论①,这0——999中有300个1

    当千位为1时,后面三个数无论是多少,整体也不会超过12345

    再加上300,当然,不能忘了千位的1,它一共贡献了1000

    当千位为2时,抱歉,路不通了

    那我们再看百位。同理:

    百位可以固定的数是0,1,2,它们总共会贡献3 * f(2)= 60

    百位上的1可以贡献: 100

    看十位:固定0,1,2,3,贡献4 * f(1)= 4

    十位上的1可以贡献: 10

    个位可以是0,1,2,3,4,5,贡献: 1

    所以答案是8121

    怎么设计程序呢?

    首先要注意到的是函数f,可以预处理一下,用数组保存每一个k的f[k]

    剩下来的操作虽然冗长,但并不繁杂,涉及到的操作如下:

    1、若正在处理的数字是1,计算出1后面的数字m,ans+=m+1(回想加2346的操作)

    2、若处理的是个位,若个位不是0,则ans++

    3、若正在处理的数字c不是个位也不是1,从0枚举到c-1,ans+=f[s-1](s表示这一位的位数,个位是1,十位是2……)

    不要忘了加上这一位上1贡献的数,也就是10 ^ (k-1)

    标程如下

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    ll f[10];
    ll n,ans;
    
    void solve(ll t,int s)
    {
    	if(t==1){//处理个位 :1234?中?出现1的可能性 
    		for(ll i=0;i<=n%10;i++){
    			if(i==1)  ans++;
    		}
    		return;//证明处理完了 
    	}
    	ll now=(n/t)%10;//当前正在处理位置上的数字 
    	if(now==1)  ans+=n%t+1;//正在处理位置上的数是1:
    	//从10000到12345万位上一共可以贡献2346个1
    	for(ll i=0;i<now;i++){//这一位上可以固定的数 (如果是1就无效了)
    		if(i==1)ans+=t;//这一位可以贡献的1的个数 
    		ans+=f[s-1];//s表示这一位是从右往左第几位 
    	}
    	solve(t/10,s-1);//处理下一位,相应地,s应该右移 
    }
    
    
    int main()
    {
    	ll a,b=1,c=1;
    	for(a=1;a<=9;a++){
    		f[a]=a;
    		for(ll i=1;i<a;i++)f[a]*=10;
    	}
    	scanf("%lld",&n);
    	while(b<n)b*=10,c++;
    	solve(b,c);
    	printf ("%lld
    ",ans);
    	return 0;
     }
  • 相关阅读:
    SpringBoot+CXF下Https调用webservice跳过安全证书的配置
    程序员的长安十二时辰:Java实现从Google oauth2.0认证调用谷歌内部api
    springboot集成activiti6.0多数据源的配置
    activiti工作流委托功能的设计和实现
    vue.js带复选框表单的增删改查
    bootstrap-treeview后台Json数据的封装及前台的显示
    你好,Spring!
    超大份线程池,干杯,兄弟!陆
    嗯!这篇多线程不错!伍
    是兄弟!就来看这篇多线程!叁
  • 原文地址:https://www.cnblogs.com/erutsiom/p/9905162.html
Copyright © 2011-2022 走看看