DESCRIPTION
Given three integers a, b, P, count the total number of digit P appearing in all integers from a to b.
The first line is a single integer T, indicating the number of test cases.
经典数位统计问题。
f[ i, j ] 用来表示 j x 10i ~ ( j + 1 ) x 10i-1 的范围内p出现的次数,有:
当 j ≠ p –> f[ i , j ] = Σ f[ i-1, k ]k=0..9
当 j = p –> f[ i , j ] = Σ f[ i-1, k ]k=0..9 + 10i-1
然后逐位进行统计。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define ll long long
ll dp[20][20];
int p;
void init(int p)
{
memset(dp,0,sizeof(dp));
ll w = 1;
for(int i = 1; i <= 10; i++)
{
for(int j = 0; j < 10; j++)
{
if(j == p)
{
dp[i][j] += w;
}
for(int k = 0; k < 10; k++)
{
dp[i][j] += dp[i-1][k];
}
}
w *= 10;
}
}
ll slove(int n)
{
char num[20];
sprintf(num,"%d",n);
ll ans = 0;
int len = strlen(num);
for(int i = 0; i < len; i++)
{
if((num[i]-'0') == p) //前位贡献值
{
int number = 0;
if(i+1 < len) // 最后一位 无贡献值
number = num[i+1]-'0';
for(int k = i+2; k < len; k++) number=number*10+(num[k]-'0');
ans += number;
}
for(int j = 0; j < (num[i]-'0'); j++)
{
ans += dp[len-i][j];
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a,b;
scanf("%d%d%d",&a,&b,&p);
init(p);
ll ans = slove(b+1)-slove(a);
printf("%lld\n",ans);
}
return 0;
}