33,025
社区成员




#include <math.h>
#include <iostream>
using namespace std;
// 以下函数计算由a到b,出现数字n的次数
int main( int argc, char* argv[] )
{
int a = 101, b = 202, n = 0;
// 如果输入非法,退出函数,返错错误码-1
if ( a >= b || n > 10 || a < 0 || n < 0 || n > b ) return -1;
int r = ( a == 0 && n == 0 ); // 如果n和a均为0,那么a=0时计1次
// 下面将从最高位到最低位进行计算,统计n在每一位出现的次数
// nPower为与b等数量级的10^x,将b取10的对数,向下取整再加1即为幂x
for ( int nPower = (int)pow( 10.0, floor( log10( (double)b ) ) + 1 );
nPower >= 10; nPower /= 10 ) // 每次循环结束后将nPower减一个数量级
{ // nTop和nBottom分别表示此次计算数值域的上界和下界
// 比如b为12345,统计6,现在计算第3位,那么nTop应为12600
int nTop = ( b / nPower ) * nPower + n * ( nPower / 10 );
int nBottom = ( a / nPower ) * nPower + n * ( nPower / 10 );
// 如果nTop大于b,就将高一位减1,如:12600>12345,则减为11600
if ( nTop > b ) nTop -= nPower; // 因为只有xx600才能在第三位出现6
// 如果nBottom加上分段长度仍小于a,或出现0的特殊情况,则将高位加1。
if ( nBottom + nPower / 10 - 1 < a || ( n == 0 && nBottom < nPower ) )
nBottom += nPower;
// 如果上下界的值正常,则进行统计运算
if ( nTop > nBottom || ( nBottom / ( nPower / 10 ) % 10 <= n &&
n <= nTop / ( nPower / 10 ) % 10 ) )
{ // 以下算法详见说明
r += ( nTop / nPower - nBottom / nPower + 1 ) * ( nPower / 10 );
if ( nTop + nPower / 10 - 1 > b ) r -= nTop + nPower / 10 - 1 - b;
if ( nBottom < a ) r -= a - nBottom;
}
}
cout << r << endl;
}