九度OJ题目1491:求1和2的个数

题目1491:求1和2的个数

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:1286

解决:382

题目描述:

给定正整数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的值。

————————————————————分割线—————————————————————————

思路参考《编程之美》P135

思想大概是:对于一个数abcde

对于c来讲,先分析c这个位置出现1的次数,c位置出现1的次数主要是靠两个部分决定的,分别是【ab】和【de】这两个数字,

当c==1时,c位置出现1的次数 = de+1+ab*100

c>1时候,    c位置出现1的次数 = ab*100+100;

c ==0时候 ,c位置出现1的次数 =ab*100;

100就是c位置所代表的位数(也就是百位)

需要注意的是,MOD的数要在每次计算时候都要模上


#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int MOD = 20123;
char s[1005];
int pow(int n)
{
    int an = 0;
    int t = 1;
    for(int i = n ;i>=0;i--)
    {
        an += (s[i]-'0')*t;
        an %=MOD;
        t*=10;
        t%=MOD;
    }
    return an;
}
int dp(int n)
{
    int an = 0;
    int t = 1;
    for(int i = strlen(s)-1 ;i>=n;i--)
    {
        an += (s[i]-'0')*t;
        an %=MOD;
        t*=10;
        t%=MOD;
    }
    return an;
}
int p(int n)
{
    int an=1;
    while(n--)
    {
        an*=10;
        an%=MOD;
    }
    return an;
}
int main()
{
    while(~scanf("%s",s))
    {
        long long ans = 0;
        int n,d;
        d = 0;
        for(int i = strlen(s)-1 ; i >= 0;i--)
        {
            int tmp = pow(i-1);
          //  cout<<tmp<<endl;
            n=s[i]-'0';
            if(n==1)
            {
                ans += dp(i+1)+1;
                ans += tmp*p(strlen(s)-i-1);
            }
            else
            {
                ans += tmp*p(strlen(s)-i-1);
                if(n>1)
                    ans+=p(strlen(s)-i-1);
            }
            if(n==2)
            {
                ans += dp(i+1)+1;
                ans += tmp*p(strlen(s)-i-1);
            }
            else
            {
                ans += tmp*p(strlen(s)-i-1);
                if(n>2)
                    ans+=p(strlen(s)-i-1);
            }
            d = n;
            ans %=MOD;
            //cout<<strlen(s)-i<<" "<<ans<<endl;
        }
        cout<<ans%MOD<<endl;
    }

}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值