Loading web-font TeX/Math/Italic

CF468C Hack it!

CF468C Hack it!

大致题意

输入a,构造一组[l,r],满足ri=lf(i)0(moda)f(i)为一个函数求一个数的各数位和。

1lr102001m1018


解题思路(二分)

先考虑确定左端点l为1,然后用二分的方法,找到最小的r满足ri=lf(i)>=a,不难发现r的取值不会超过长整型范围。然后在区间上进行双指针的递增,即可找到答案。

为什么这样的时间复杂度是对的呢?我也不知道(((

根据出题人的说法:数位和的变化比较随机,没有出现明显的循环节,所以变两下就会变到正确答案。

于是这道题就愉快的做完了


解题思路 (直接计算)

除了可以二分外,这道题也同样可以用数学方法推公式直接计算。

参考题解 CF468C 【Hack it!】 - da32s1da 的博客

因为有f(x)=y,所以很自然的可以推出f(x+1018)=f(x)+1,并以此类推可以得到

f(x+1018+1)=f(x)+2

f(x+1018+2)=f(x)+3

...

所以对于原式,我们可以得到,1018i=1f(i)10181i=0f(i)+1(moda)
以此类推
1018+1i=2f(i)10181i=0f(i)+2(moda)

...

我们设10181i=0f(i)=p

经过一系列式子的变换,就可以得到1018+ap1i=apf(i)0(moda),(具体过程可以参考上面那篇博客)

ap1018+ap1即为我们所求的[l,r]值。

p为一定值,我们可以手动计算(当然也可以借助数位dp程序),得到p=811018moda

于是就可以很简洁地完成这道题。


代码(二分)

/* Generated by powerful Codeforces Tool
 * You can download the binary file in here https://github.com/xalanq/cf-tool (Windows, macOS, Linux)
 * Author: icey_z
 * Time: 2022-07-02 14:06:30
 **/
#include <bits/stdc++.h>
using namespace std;
using ll  = long long;
using pii = pair<int, int>;

const int INF   = 0x3f3f3f3f;
const ll  LLINF = 0x3f3f3f3f3f3f3f3f;

ll mod;

ll cal(ll x)
{
    ll ans = 0;
    for (ll i = 1; i <= x; i *= 10LL) {  //低到高枚举位
        ll p = x / (i * 10);             //低位的和
        ans += 45 * i * p;
        ll q = (x / i) % 10;
        for (int j = 1; j < q; j++) {  //当前位的和
            ans += j * i;
        }
        ll t = x - (x / i) * i;  //高位的和
        ans += (t + 1) * q;
    }
    return ans;
}

ll calc(ll x)
{
    ll ans = 0;
    while (x) {
        ans += x % 10;
        x /= 10;
    }
    return ans;
}

void solve()
{
    cin >> mod;
    ll l = 1, r = 1e17;
    ll res = 0;
    while (l <= r) {
        ll mid = (l + r) / 2;
        if (cal(mid) >= mod) {
            res = mid;
            r   = mid - 1;
        }
        else
            l = mid + 1;
    }
    r      = res;
    l      = 1;
    ll cur = cal(r);
    // cout << l << " " << r << "\n";
    while (cur != mod) {
        cur -= calc(l++);
        while (cur < mod) {
            cur += calc(++r);
        }
    }
    cout << l << " " << r << "\n";
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int t;
    t = 1;
    while (t--) {
        solve();
    }
    return 0;
}
posted @   icey_z  阅读(77)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示