ARC090:Number of Digits(思维 & 计数)

F - Number of Digits


Time limit : 2sec / Memory limit : 256MB

Score : 900 points

Problem Statement

For a positive integer n, let us define f(n) as the number of digits in base 10.

You are given an integer S. Count the number of the pairs of positive integers (l,r) (lr) such that f(l)+f(l+1)++f(r)=S, and find the count modulo 109+7.

Constraints

  • 1S108

Input

Input is given from Standard Input in the following format:

S

Output

Print the answer.


Sample Input 1

Copy
1

Sample Output 1

Copy
9

There are nine pairs (l,r) that satisfies the condition: (1,1)(2,2)(9,9).


Sample Input 2

Copy
2

Sample Output 2

Copy
98

There are 98 pairs (l,r) that satisfies the condition, such as (1,2) and (33,33).


Sample Input 3

Copy
123

Sample Output 3

Copy
460191684

Sample Input 4

Copy
36018

Sample Output 4

Copy
966522825

Sample Input 5

Copy
1000

Sample Output 5

Copy
184984484

题意:给出S,问有多少个正整数区间[L,R]满足L到R的数位和为S。

思路:定义dig[i]为i的数位。

首先观察到S<=1e8,对于数位是8的数字(10^8-10^7个)已经超过了1e8个,因此有如下限制:

①当L>=10000000时,dig[R]-dig[L]<=1;

②当L<10000000时,R<=23000000。

对于情况②,用尺取法即可。

对于情况①,我们枚举区间长度t,假设t由x个数位i的数组成和y(y可以为0)个数位为i+1的数组成,于是有:

x+y=t

i*x+(i+1)*y=S即i*(x+y)+y=S即i*t+y=S

又因为y<t,所以i=S/t,y=S%t,也就是说当L>=1e7时对于每个区间长度t,i都被唯一决定了,最后归纳如下:

如果长度t不能整除S,即有余数y,也就是dig[R]-dig[L]=1,L是唯一确定的,答案加1。

如果长度t整除S,即y=0,也就是dig[R]-dis[L]=0,即L和R同属于数位S/t的部分,显然答案加上这部分有几个数-t+1。

# include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
typedef long long LL;
const int maxn = 23000000;
short dig[maxn+1];
inline void add(int &x, int y)
{
    x+=y;
    if(x>=mod) x-=mod;
}
int qmod(LL a, int b)
{
    LL res = 1;
    for(;b;b>>=1)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
    }
    return (int)res;
}
int main()
{
    for(int i=1; i<=maxn; ++i) dig[i] = dig[i/10]+1;
    int n, ans=0;
    scanf("%d",&n);
    for(int i=1, j=1, s=0; i<1e7; ++i)
    {
        while(s<n) s+=dig[j],++j;
        if(s==n) add(ans, 1);
        s -= dig[i];
    }
    for(int i=1; i<=n/8; ++i)
    {
        if(n%i==0) add(ans, ((qmod(10,n/i)-qmod(10,n/i-1)-i+1)%mod+mod)%mod);
        else add(ans, 1);
    }
    printf("%d\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值