题目大意:
求[l,r]之间的整数中数码0~9各自出现次数。思路:
数位DP。1 #include2 #include 3 #include 4 typedef long long int64; 5 inline int64 getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int64 x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');10 return x;11 }12 const int64 pow[]={1ll,10ll,100ll,1000ll,10000ll,100000ll,1000000ll,10000000ll,100000000ll,1000000000ll,10000000000ll,100000000000ll,1000000000000ll};13 int64 cnt[10];14 inline void calc(const int64 &n,const int &sgn) {15 if(n==-1) { //如果从0开始算,那么单独一个0也要算进去(不然会被当作前导0) 16 cnt[0]++;17 return;18 }19 //以12345为例 20 for(register int k=1;k<10;k++) { //枚举数字21 for(register int i=1;;i++) { //枚举数位22 int64 high=n/pow[i],low=n%pow[i-1];//高位、低位 23 int cur=n%pow[i]/pow[i-1];//当前位(比如取了3) 24 if(cur==k) cnt[k]+=(high*pow[i-1]+low+1)*sgn;//00300~11399+12300~12345 25 if(cur>k) cnt[k]+=(high+1)*pow[i-1]*sgn;//00200~11299+12200~12299 26 if(cur n) break;28 }29 }30 for(register int i=1;;i++) { //单独计算031 int64 high=n/pow[i],low=n%pow[i-1];32 int cur=n%pow[i]/pow[i-1];33 //都比原来少乘一个pow[i-1],因为要去掉前面全是0的情况 34 if(cur) {35 cnt[0]+=high*pow[i-1]*sgn;36 } else {37 cnt[0]+=((high-1)*pow[i-1]+low+1)*sgn;38 }39 if(pow[i]>n) break;40 }41 }42 int main() {43 int64 l=getint(),r=getint();44 calc(r,1);45 calc(l-1,-1);46 for(register int i=0;i<9;i++) {47 printf("%lld ",cnt[i]);48 }49 printf("%lld\n",cnt[9]);50 return 0;51 }