题解 AT2341 【Increasing Numbers】
广告 && 吐槽
蒟蒻のblog
请各位同学不要忽略这题的想出来的思维难度,再怎么说普及-也太过分了,代码难度不是决定题目难度的唯一标准!
思路
首先,我们观察一下上升数的性质
可以发现,它一定可以表示为最多9个全是1的数字的和
那么我们设
我们令
那么可以写出这样的式子
我们发现,
所以上式可以写成:
我们把9乘过去,再把右边的
我们发现:右边这个东西,如果在所有的10的幂加起来的过程中,能够不进位的话,那么它的数位和一定是9k
如果它发生了进位,因为1次进位一定是-10+1,总数位和-9,而9k是9的倍数,所以这个东西的数位和一定是一个小于9k的9的倍数
再看左边,我们发现,实际上我们需要满足的就是
所以我们只需要求出最小的
由数学归纳法不难证明,本题中
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[1000010];int a[1000010];
int main(){
scanf("%s",s);int n=strlen(s),i,j,sum=0,k;
for(i=1;i<=n;i++) a[i]=(s[n-i]-'0')*9;
for(i=1;i<=n;i++){
a[i+1]+=a[i]/10;a[i]%=10;
}
if(a[n+1]) n++;
for(i=1;i<=n;i++) sum+=a[i];
for(k=1;k<=n*10;k++){
a[1]+=9;sum+=9;
j=1;
while(j<=n){
if(a[j]<10) break;
sum-=10;a[j]-=10;
sum++;a[j+1]++;
j++;
if(j==n&&a[j+1]) n++;//别忘了有可能加一位
}
if(sum<=9*k){//注意这里一定不要写成等于了
printf("%d\n",k);return 0;
}
}
}