题意:
给定
n
n
n 和
k
(
1
≤
n
≤
150
,
0
≤
k
≤
9
)
k~(1 \leq n \leq 150,0 \leq k \leq 9)
k (1≤n≤150,0≤k≤9) ,找到最小的
x
x
x ,使得:
f
(
x
)
+
f
(
x
+
1
)
+
⋯
+
f
(
x
+
k
)
=
n
f(x)+f(x+1)+ \cdots + f(x+k)=n
f(x)+f(x+1)+⋯+f(x+k)=n
其中
f
(
x
)
f(x)
f(x) 表示
x
x
x 的十进制数字的和
分析:
因为 0 ≤ k ≤ 9 0 \leq k \leq 9 0≤k≤9 ,所以最多会产生一次进位,
Ⅰ:
首先考虑没有进位的情况,那么容易想到枚举 x x x 个位数上的数,求出 x x x 到 x + k x+k x+k 个位数的和 s u m sum sum,然后判断 i f ( ( n − s u m ) % ( k + 1 ) = = 0 ) if((n-sum)\%(k+1)==0) if((n−sum)%(k+1)==0) 对应有没有解;
Ⅱ:
然后考虑有进位的情况,事先需要明确一点,因为是求最小值,所以除了个位数,是不会存在 9 + 1 9+1 9+1 进位的,因为产生一个 9 + 1 9+1 9+1 进位就等价于十进制数和减少了 8 8 8 ,得不尝试;所以个位数产生进位的情况下 十位数上最大为 8 8 8 ;
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define frep(i,a,b) for(int i=a;i>=b;i--)
int n,k;
int sum[10][10]; //sum[i][j],表示 i~j 的和
void init()
{
rep(i,0,9)rep(j,0,9){
int a=0;
if(i<=j) rep(z,i,j) a+=z;
else{
rep(z,i,9) a+=z;
rep(z,1,j) a+=z;
}
sum[i][j]=a;
}
}
int main()
{
//freopen("1.txt","r",stdin);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
init();
int t;
cin>>t;
while(t--)
{
vector<string>ANS;
cin>>n>>k;
rep(start,0,9)
{
int end=(k+start)%10;
int num=sum[start][end];
if(num>n) continue; //个位数的和就大于n,肯定无解
if(num==n&&start<=end) //最简单的解
{
string s;
s+=(start+'0');
ANS.pb(s);
continue;
}
int m=n-num,cnt=0;
if(start>end) cnt=end+1;
// m 表示除开个位数的和
// cnt 表示进位的数的个数
if(cnt==0) //没有产生进位
{
if(m%(k+1)!=0) continue;
string s;
s+=(start+'0');
m/=(k+1);
int tim=m/9;
while(tim--) s+='9';
if(m%9>0) s+=(m%9)+'0';
//从十位数位往上填,没有进位,肯定尽量填9,以此满足x最小的要求
reverse(s.begin(),s.end());
ANS.pb(s);
}
else if(m>=cnt) //有进位的情况,进位的数的十位数位都加1,所以得比较
{
if((m-cnt)%(k+1)==0)
{
int lft=m-cnt;
lft/=(k+1);
string s;
s+=(start+'0');
if(lft>0) //因为个位数有进位,十位数位上最多填8
{
if(lft<=8) s+=(lft+'0'),lft=0;
else s+='8',lft-=8;
}
int tim=lft/9;
while(tim--) s+='9';
if(lft%9>0) s+=(lft%9)+'0';
reverse(s.begin(),s.end());
ANS.pb(s);
}
}
}
if(ANS.size()==0) cout<<-1<<endl;
else{
int ML=1e9;
for(string s:ANS) ML=min(ML,(int)s.length()); //先找到最小解的长度
vector<string>Ne;
for(string s:ANS) if(s.length()==ML) Ne.pb(s);
sort(Ne.begin(),Ne.end());
cout<<Ne[0]<<endl;
}
}
}