这类题大的方向都是写一个函数f(n)表示1到n中所有的数一共有多少个0,那么最终的答案就是f(n)-f(m-1)所以关键就是如何写f,这是一个神奇的方法。。。
首先比如n=12345,把其中一位数假设为0,那么这位数左边的种数*右边的种数就等于当这位数确实为0时所需要写下的0的个数
具体一点:
mid left right x ans
12345 0 1 0
5 1234 0+5*1 10 1234*1
4 123 0+5*1+4*10 100 1234*1+123*10 //比如此时左边有1-123共123个,右边有0-9共10个,乘法原理相乘可得
3 12 0+5*1+4*10+3*100 1000 1234*1+123*10+12*100
2 1 0+5*1+4*10+3*100+2*2000 10000 1234*1+123*10+12*100+1*1000
上述情况因为原数的某一位不为0,所以当我们把这一位假设为0后,之后得到的数无论如何也不可能大于原数,比如(1-123)0(0-9)无论如何也不可能大于12345
但是如果当原数的某一位确实为0时,比如12305,为了保证所假设得到的数不大于原数,这时候答案就为122*10+6 即前122位*10不变,当左边为123时,右边只能小于等于5
此外我们假设位0的右边的位数是一定的,比如120345,0右边必定是从000到345即一定会有三位数,当假设位前移时如10x345,无论x是否为0,此时假设位0的右边有4位数,与之前的三位数肯定不一样,所以整个数也不一样,所以不用担心数字会重复
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define mod 1000000007
using namespace std;
ll solve(ll left){
ll mid,ans=0,right=0,x=1;
while(left>=10){
mid=left%10;
left/=10;
if(mid) ans+=left*x;
else ans+=(left-1)*x+(right+1);
right+=mid*x;
x*=10;
}
return ans;
}
int main(){
ll m,n;
while(cin>>m>>n&&m!=-1&&n!=-1){
cout<<solve(n)-solve(m-1)<<endl;
}
return 0;
}