• [AtCoder arc090F]Number of Digits


    Description

    题库链接

    (d) 在十进制下的位数为 (f(d)) 。给出询问 (S) ,求有多少对 ((l,r)) 使得 [sum_{i=l}^r f(i)=S]

    (1leq Sleq 10^8)

    Solution

    颓了题解...

    注意到当数字越大时 (f(r)-f(l)) 会越小。

    分两种情况讨论:

    1. (f(l)leq 7) ,这时可以用尺取法来做,可以发现它的右界为 (10^7+frac{10^8}{8}=22500000)

    2. (f(l)geq 8) ,我们依旧可以分两种情况来考虑:

      1. (f(r)-f(l)=0) ,此时显然选的数都是位数相同的,我们可以统计这种位数的个数 (sum) ,该种情况的答案 (sum-f(l)+1)

      2. (f(r)-f(l)=1) 。假设取的数个数为 (t) ,即 (r-l+1=t) ,取长度为 (f(l)) 的个数为 (x) ,长度为 (f(r)) 的个数为 (y)[egin{cases}x+y=t\xcdot f(l)+ycdot f(r)=Send{cases}]
        那么 (f(l)cdot t+y=S) 我们可以枚举 (t) ,容易发现 (egin{cases}y=S~mod~t\x=t-S~mod~tend{cases}) ,即对于每个 (t) ,都可以解出唯一解。值得注意的是这方面的解会和上面的解重复,即当 (f(l)mid S) 这里会计算一次。

    综上可以分情况处理。

    Code

    //It is made by Awson on 2018.2.3
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int l1 = 10000000;
    const int l2 = 25500000;
    const int yzh = 1e9+7;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    int s, f[l2+5];
    
    int quick_pow(int a, int b) {
        int ans = 1;
        while (b) {
        if (b&1) ans = 1ll*ans*a%yzh;
        a = 1ll*a*a%yzh, b >>= 1;
        }
        return ans;
    }
    int count1(int n) {
        int ans = 0, r = 0, cnt = 0;
        for (int i = 1; i < l1; i++) {
        cnt -= f[i-1];
        while (cnt+f[r+1] <= s && r < l2) cnt += f[++r];
        if (cnt == s) ++ans;
        if (r == l2) break;
        }
        return ans;
    }
    int count2(int n) {
        int lim = n/8, ans = lim;
        for (int t = 1; t <= lim; t++)
        if (n%t == 0) {
            int len = n/t;
            (ans += (1ll*quick_pow(10, len-1)*9%yzh-t)%yzh) %= yzh;
        }
        return ans;
    }
    void work() {
        for (int i = 1, r = 10, cnt = 1; i < l1; i++, i = r, r = r*10, cnt++)
        for (int j = i; j < r; j++) f[j] = cnt;
        for (int i = l1; i <= l2; i++) f[i] = 8;
        read(s);
        writeln(((count1(s)+count2(s))%yzh+yzh)%yzh);
    }
    int main() {
        work();
        return 0;
    }
  • 相关阅读:
    Hack World和CTFHub布尔注入记录
    MySQL updatexml()、extractvalue() 报错型SQL注入
    常见的Web源码泄漏漏洞及其利用(转载记录)
    大白
    [强网杯 2019]随便注
    [极客大挑战 2019]LoveSQL 1
    Mysql--事物
    Android深度探索-卷1第十章心得体会
    Android深度探索-卷1第八章心得体会
    Android深度探索-卷1第九章心得体会
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8408892.html
Copyright © 2020-2023  润新知