【输入样例1】
2 22
【输入样例2】
2 100
输出样例1:
6
输出样例2:
20
原本想写一个dp的代码,结果发现写成了模拟
一定范围的数里有多少个2是固定的比如说0-9,0-99,0-999这样的几位数中的2的个数都可以递推出来(其实hxy用的打标也可以)
然后就可以把数的每一位分解,然后计算出0-这一位代表的数中有多少个2,然后相加
要注意的是这个数中本身就有2的情况。如果这一位是2,那么往后所有的数都会多出一个2
求出0-l,0-r中2的个数,然后相减即可。注意如果l里本身就有2的话需要再加上2的数量
【代码】
#include<iostream> #include<cstring> #include<cstdio> using namespace std; long long l,r,n,m,ans; long long mi[20],f[20]; inline int doit(int now){ long long k=now,weishu=0,tot=0,num=0,ans=0; while (k>0){ num=k%10; weishu++; if (num==0){ k/=10; continue; } tot=f[weishu]; if (num>2) tot-=(10-num)*f[weishu-1]; else if (num<=2){ tot=num*f[weishu-1]; if (num==2) tot++; } ans+=tot; k/=10; } return ans; } int main(){ scanf("%lld%lld",&l,&r); mi[0]=1; for (int i=1;i<=10;++i) mi[i]=mi[i-1]*10; f[1]=2; for (int i=1;i<=10;++i) f[i]=f[i-1]*10+mi[i-1]; n=doit(l); long long l1=l; long long x=0,y=0,z=1; while (l>0){ x=l%10; if (x==2) n+=y; y=x*z+y; z*=10; l/=10; } m=doit(r); x=0,y=0,z=1; while (r>0){ x=r%10; if (x==2) m+=y; y=x*z+y; z*=10; r/=10; } ans=m-n; l=l1; while (l>0){ int x=l%10; if (x==2) ans++; l/=10; } printf("%lld\n",ans); }