桁和 / Digit Sum -atcoder

2 篇文章 0 订阅

Problem Statement

For integers b(b≥2) and n(n≥1), let the function f(b,n) be defined as follows:

  • f(b,n)=n, when n<b
  • f(b,n)=f(b, floor(nb))+(n mod b), when nb

Here, floor(nb) denotes the largest integer not exceeding nb, and n mod b denotes the remainder of n divided by b.

Less formally, f(b,n) is equal to the sum of the digits of n written in base b. For example, the following hold:

  • f(10, 87654)=8+7+6+5+4=30
  • f(100, 87654)=8+76+54=138

You are given integers n and s. Determine if there exists an integer b(b≥2) such that f(b,n)=s. If the answer is positive, also find the smallest such b.

Constraints

  • 1≤n≤1011
  • 1≤s≤1011
  • n, s are integers.

Input

The input is given from Standard Input in the following format:

n
s

Output

If there exists an integer b(b≥2) such that f(b,n)=s, print the smallest such b. If such b does not exist, print -1 instead.


Sample Input 1

Copy

87654
30

Sample Output 1

Copy

10

一道看题解废了九牛二虎之力才看懂的数论题,感觉这个世界没有数学渣渣的容身之地OTZ

题意大意是给出来一个数字n,他在b进制下各位数的和为s,现在给出n和s ,求最小的数字b

【这里贴一下其他博客的计算图←一个不会敲公式的渣渣,原地址点击这里

 而后是代码,思路基本上是先调用check函数遍历所有的小于根号n的b值,如果有结果,直接return 0 就可以结束了(毕竟是寻找最小值),若找不到结果,继续进行下一步判断。

若s=n,毫无疑问这个b进制在大于n的情况下都可以,而最小值是n+1

若s>n,那么不存在这样一个b使结果成立。

然后遍历大于根号n的情况

这里就是我一直死活没有看懂的地方,现在得出来的自己的理解似乎是说的过去的,但是并不完全确定是否正确,还需要再进一步的去仔细想想。

在b>=根号n的时候,此时x1可以表示为  根号n/(b-1),由此可以确定其范围大约为  n-s/(根号n-1)+1←因为这个下取整,然后进行遍历【此处原博客代码n-s/根号n,一直没有搞懂为什么他没有这个-1,但是我加上这个-1之后运行也AC,但是不知道对方是图简单还是另有我不知道的深意】,最后进行判断,若满足条件,则输出结果,否则输出-1

#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
#include<sstream>
#include<cstring>
#include<algorithm>
#include<string>
#define LL long long
using namespace std;
LL n,s,b;
bool check(LL n, LL b)
{
    long long res = 0;
    while(n > 0)
    {
        res += n%b;
        n/=b;
    }
    return res == s;
}
int main()
{
    //int n,s,b;
    cin >> n >> s;
    LL temp = (LL)sqrt(n)+1;
    for(LL i = 2; i <= temp; i ++)
    {
        if(check(n,i))
        {
            cout << i << endl;
            return 0;
        }
    }
    if(s == n)
    {
        cout << n+1 << endl;
        return 0;
    }
    if(s > n)
    {
        cout << "-1" << endl;
        return 0;
    }
    LL temp1 = n - s, temp2 = temp1/(temp-1) + 1;
    for(int i = temp2; i >= 1; i --)
    {
        if(!(temp1%i) && s - i <= temp1/i && s >= i && i<= temp1/i)
        {
            cout << temp1/i + 1 << endl;
            return 0;
        }
    }
    cout << "-1" << endl;
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值