[??记录]AT2341 [AGC011E] Increasing Numbers
command_block
2021-04-28 11:57:44
**题意** : 称一个十进制数是“递增的”,当且仅当其从高到低的每个数位都不大于下一个数位。
给出数 $n$ ,求其最少能被表示为几个递增的数的和。
$n\leq 10^{500000}$ ,时限 $\texttt{2s}$。
------------
十进制下一个递增的数等效于 $9$ 个 $111...111$ (长度可能为零) 的和。
二分答案,转化为判定性问题。
即判定是否有 $p_i$ 使得下式成立 :
$$n=\sum\limits_{i=1}^{9k}\dfrac{10^{p_i}-1}{9}$$
若成立,说明答案可以 $\leq k$ 。
可以变形为 :
$$9n+9k=\sum\limits_{i=1}^{9k}10^{p_i}$$
于是,计算出 $9n+9k$ ,然后查看数位和是否 $\leq 9k$ 即可。
需要高精度。
```cpp
#include<algorithm>
#include<cstring>
#include<cstdio>
#define MaxN 500500
using namespace std;
int n,t[MaxN],tn;
char s[MaxN];
bool chk(int k)
{
for (int i=1;i<=n;i++)t[i]=(s[i]-'0')*9;
t[1]+=k*9;
for (int i=1;t[i]||i<=n;i++){
t[i+1]+=t[i]/10;
t[i]%=10;
}
int c=0;
for (int i=1;i<=n+50;i++){
c+=t[i];
t[i]=0;
}
return c<=9*k;
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
reverse(s+1,s+n+1);
int l=1,r=n,mid;
while(l<r){
mid=(l+r)>>1;
if (chk(mid))r=mid;
else l=mid+1;
}printf("%d",l);
return 0;
}
```