嘘~ 正在从服务器偷取页面 . . .

[ABC044D] Digit Sum 题解


[ABC044D] Digit Sum 题解

题目链接:[ABC044D] Digit Sum

题意

对于任意非负整数 \(x\)\(m(2\le m)\) ,定义 \(f_m(x)\)\(x\)\(m\) 进制下的各位数字之和。

例如\(f_{10}(87654)=8+7+6+5+4=30,~f_{100}(87654)=8+76+54=138\) 。给定两个整数 \(x\)\(n\)

你需要计算是否存在某个 \(m\ge 2\) 使得 \(f_m(x)=n\)

如果存在,输出最小的满足条件的 \(m\) ;如果不存在,输出 \(−1\)

数据范围

\(1 \le x,n \le 10^{11}\)

\(x\) 化为 \(m\) 进制后为 \(\overline{x_1x_2\dots x_t}\)

不难发现当 \(t \ge 3\) 时, \(m\le \sqrt{x}-\epsilon,\epsilon \in \mathbb{N}\)

例如当 \(t=3\) 时,设 \(x\) 化为 \(m\) 进制后为 \(\overline{abc}\) ,则 \[ x=am^2+bm+c \] 显然有 \(m\le \sqrt{x}-\epsilon,\epsilon \in \mathbb{N}\)

因此我们暴力枚举所有 \(m\le \sqrt{x}-\epsilon,\epsilon \in \mathbb{N}\) ,对应 \(t\ge 3\) 的情况

接下来 \(m > \sqrt{x}-\epsilon,\epsilon \in \mathbb{N}\) 的情况,直接枚举 \(m\) 肯定是不行的

注意到此时 \(x\) 满足 \[ x=am+b \] 因为有 \(m > \sqrt{x}-\epsilon,\epsilon \in \mathbb{N}\) ,因此 \(a \le \sqrt{x}-\epsilon^{\prime},\epsilon^{\prime} \in \mathbb{N}\)

于是我们只要枚举这个 \(a\) ,然后判断此时的 \(m=\frac{x-(n-a)}{a}\) 是否合法即可

这里的合法指 \(x\) 在当前 \(m\) 进制下是 \(am+b\)

时间复杂度 \(O(\sqrt{x})\)

代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <random>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)()

int x,n,ans;
void check(int m)
{
    if(m<2) return;
    int res=0,tmp=x;
    while(tmp)
    {
        res+=tmp%m;
        tmp/=m;
    }
    if(res==n) ans=min(ans,m);
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> x >> n; ans=INF;
    for(int m=2; m*m<=x; m++) check(m);
    if(x==n) ans=min(ans,n+1);
    for(int a=1; a*a<=x; a++) check((x-(n-a))/a);
    if(ans==INF) cout << "-1\n";
    else cout << ans << '\n';
    return 0;
}

题外话

AtCoder改过题号了,这篇是以前写的

然后就很好笑的是题目上的题号和实际网址上的题号又是不一样的


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录