题目链接
题意
定义f(x)为x在十进制下的各位数字之和。
给定a,需要你给出一个l,r(1 <= l <= r <= 1e200)使得(f(l) + … +f(r))能被a整除。
题目确保有解。
数据
(1 <= a <= 1e18)
输入
46
126444381000032
输出
1 10
2333333 2333333333333
解题方法:
姿势1:[一套尺取+二分连招]
令s(x) = f(1)+f(2)+…+f(x)。
我们只需找到s(R)%a = s(L-1)%a就美滋滋了
我们使用二分查询找到最小的且满足g(R)>=a
的值R, 接下来令L=1,然后跑一个双指针,调整
L,R的值即可。至于s(x)怎么求,我们把每一个
数位对答案的贡献加起来即可。

姿势2:[构造]
注意到f(x+1e18)=f(x)+1。
故s(x+1e18)=s(1e18)+s(x)+x。
即s(x+1e18)-s(x) = s(1e18)+x
再注意到:s(10^x)= 4510^(x-1) x + 1
L = a-s(1e18)%a+1,R = L + 1e18- 1
于是一组合法解就神不知鬼不知觉地构造出来了

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a;
LL g(LL x)//计算g(x)这里想了好久好久
{
    LL ans = 0;
    for(LL ten = 1; ten <= x; ten *= LL(10)){
        LL dig = (x / ten) % (LL)10;
        LL cur = 0;
        LL m = x / ((LL)10 * ten);
        LL n = x % ten;
        for(LL i = 1; i < dig; i++) cur += i;
        ans += (m + 1) * cur * ten;
        ans += dig * (m * ten + n + 1);
        for(LL i = dig + 1; i <= 9; i++){
            ans += m * ten * i;
        }
    }
    return ans;
}
LL getDig(LL x)
{
    LL ans = 0;
    while(x)
    {
        ans += x % 10;
        x /= 10;
    }
    return ans;
}
int main()
{
    cin >> a;
    LL l = 1, r = 1e17;
    while(l < r)
    {
        LL mid = (l + r) >> 1;
        if(g(mid) < a){
            l = mid + 1;
        }
        else{
            r = mid;
        }
    }
    l = 1;
    LL sum = g(r) - g(l - 1);
    while(1)
    {
        if(sum < a){
            sum += getDig(++r);
        }
        else if(sum > a){
            sum -= getDig(l++);
        }
        else{
            break;
        }
    }
    cout << l << " " << r << endl;
    return 0;
}