AtCoder Regular Contest 060--D - 桁和 / Digit Sum--数论+思维

D - 桁和 / Digit Sum


Time Limit: 2 sec / Memory Limit: 256 MB

Score : 500500 points

Problem Statement

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

  • f(b,n)=nf(b,n)=n, when n<bn<b
  • f(b,n)=f(b,floor(n/b))+(n mod b)f(b,n)=f(b,floor(n/b))+(n mod b), when n≥bn≥b

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

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

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

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

Constraints

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

Input

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

nn
ss

Output

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


Sample Input 1 Copy

Copy

87654
30

Sample Output 1 Copy

Copy

10

Sample Input 2 Copy

Copy

87654
138

Sample Output 2 Copy

Copy

100

Sample Input 3 Copy

Copy

87654
45678

Sample Output 3 Copy

Copy

-1

Sample Input 4 Copy

Copy

31415926535
1

Sample Output 4 Copy

Copy

31415926535

Sample Input 5 Copy

Copy

1
31415926535

Sample Output 5 Copy

Copy

-1

给出n和s求一个进制b使得n在b进制下各位数之和为s

详细思路:

第一种情况
    x0+x1*b^1+x2*b^2+...=n
    x0+x1+x2+...=s
    这个时候b^2<=n
    所以b<=根号n

    这个时候暴力枚举即可

第三种情况暴力枚举
    x0+x1*b^1=n;
    x0+x1=s;
    这个时候联立二式子
    得到x1*(b-1)=n-s
    我们枚举x1
,然后判断是否成立,包括题目条件以及进制常识

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,s;
bool check(ll base)
{
    ll tmp=n;
    ll ans=0;
    while(tmp)
    {
        ans+=tmp%base;
        tmp/=base;
    }
    return ans==s;
}
bool check(ll i,ll sum)
{
    ll a1=s-i;//x0
    ll a2=sum/i+1;//b
    if(a1>=0&&a1<a2&&i<a2)return 1;
    //就是说你的x0,x1肯定是要比进制base小的,而且大于0
    return 0;
}
int main()
{
    scanf("%lld%lld",&n,&s);
    /*第一种情况
    x0+x1*b^1+x2*b^2+...=n
    x0+x1+x2+...=s
    这个时候b^2<=n
    所以b<=根号n
    这个时候暴力枚举即可
    */
    ll Sn=(ll)(sqrt(n))+1;
    ll base;
    for(base=2;base<=Sn;base++)
    {
        if(check(base))
        {
            printf("%lld\n",base);
            return 0;
        }
    }
    /*
    第二种情况
    */
    if(n<=s)
    {
        if(n==s)
        {
            printf("%lld\n",n+1);
        }else
        {
            printf("-1\n");
        }
        return 0;
    }
    /*
    第三种情况暴力枚举
    x0+x1*b^1=n;
    x0+x1=s;
    这个时候联立二式子
    得到x1*(b-1)=n-s
    我们枚举x1,然后判断是否成立,包括题目条件以及进制常识
    */
    ll sum=n-s;
    ll up=sum/Sn+1;
    for(ll i=up;i>=1;i--)
    {
        if(!(sum%i)&&(check(i,sum)))
        {
            printf("%lld\n",sum/i+1);
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值