九度1491 求1和2的个数

链接:
http://ac.jobdu.com/problem.php?pid=1491

题目描述:

给定正整数N,函数F(N)表示小于等于N的自然数中1和2的个数之和,例如:1,2,3,4,5,6,7,8,9,10序列中1和2的个数之和为3,因此F(10)=3。输入N,求F(N)的值,1<=N<=10^100(10的100次方)若F(N)很大,则求F(N)mod20123的值。

思路:
这题的数据量很大,首先肯定是要用字符串数组来存,然后从最低位开始,逐位分析,该位出现的次数是多少。
以abcdef为例,假如我们现在要求1在所有不超过它的自然数中出现的次数。
我们从最后一位开始,也就是f,此时f的高位是abcde,低位为0。那么这一位是1的数一共出现了多少次呢,需要看f与1的关系。
这个关系在最后一位不好叙述,我们以d为例,它的高位是abc,低位是ef,此时factor=100。
我们可以仔细想想,如果d=0,说明此位为1的数有abc*100。
如果d==1,说明此位为1的数有abc*100加上ef+1
如果d>1,那么就直接用(abc+1)*100就可以了
这样会计算重复的数,但是这是没有关系的,因为计算的是所有1的个数。

#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
using namespace std;
#define mod 20123
string num;
int count(int x){
    int k = num.length() - 1;
    int factor = 1;
    int ans = 0;
    while (k >= 0){
        int lownum = 0;
        int highnum = 0;
        int currnum = 0;
        for (int i = 0; i < k; i++){ //从最低位开始,计算它的高位和低位
            highnum = (highnum * 10 + (num[i]-'0')) % mod;
            cout << "highnum = " << highnum << endl;
        }
        for (int i = k + 1; i < num.length(); i++){
            lownum = (lownum * 10 + (num[i]-'0')) % mod;
            cout << "lownum = " << lownum << endl;
        }
        currnum = num[k] - '0';
        if (currnum < x){  //下面是分情况,看当前位是否大于1或者2
            ans = (ans + (highnum * factor) % mod) % mod;
        }
        else if (currnum == x){
            ans = (ans + (highnum * factor) % mod + lownum + 1) % mod;
        }
        else if (currnum > x){
            ans = (ans + ((highnum + 1) * factor) % mod) % mod;
        }
        factor = (factor * 10) % mod;
        k--;
    }
    return ans;
}

int main(){
    while (cin>>num){
        int ans = (count(1) + count(2)) % mod;
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值