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;
}