先进行预处理
s[pos][val]
s[3][5]表示 0~500的1的个数
所以s[3][5]+=s[3][4](0~400);
s[i][j]+=s[i][j-1];
s[3][5]+=s[2][9]+ss[1][9](0~99);
for(int k=i-1;k>=1;--k)
s[i][j]+=s[k][9];
特殊的当 j==1时,s[i][j]+=1;
当j==2时,s[i][j]+= 10^i-1;
查询:0~b 1的个数- 0~a 1的个数
如896 = 0~6 1的个数 +0~90 1的个数 +0~800 1的个数
特别的 当某位为1的时候
如 1819= 0~9 + (0~10+ 9) +( 0~800) +(0~1000 +819);
其中原理自己体会体会吧。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#define MAX_SIZE 20
using namespace std;
typedef long long llint;
llint s[MAX_SIZE][MAX_SIZE];
void init()
{
memset(s,0,sizeof(s));
for(llint i=1;i<MAX_SIZE;++i)
{
for(llint j=1;j<=9;++j)
{
if(j==1)
s[i][j]=1;
for(llint k=i-1;k>=1;--k)
s[i][j]+=s[k][9];
if(j==2)
{
llint t=1,k=i-1;
while(k--) t*=10;
s[i][j]+=t-1;
}
s[i][j]+=s[i][j-1];
}
}
}
llint sum(llint x)
{
llint S=0;
llint i=1;
llint y=x;
while(y)
{
if((y%10)==1)
{
llint t=1,k=i-1;
while(k--) t*=10;
if(i<=18)//10^19 long long 内存溢出
S+=s[i++][y%10]+x%t;
else S+=s[i++][y%10]+x+1;
}
else S+=s[i++][y%10];
y/=10;
}
return S;
}
int main()
{
llint a,b;
init();
while(~scanf("%lld%lld",&a,&b))
{
if(a>b)
printf("0\n");
else printf("%lld\n",sum(b)-sum(a-1));
}
return 0;
}