原题:http://acm.fzu.edu.cn/problem.php?pid=1896
思路:
dp[i][j]表示前i位且最高位为j的魔法数个数;
然后将范围相减;
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int dp[15][15];
int m;
void pre()
{
for(int i = 0;i<10;i++)
dp[1][i] = 1;
for(int i = 2;i<12;i++)
{
for(int j = 0;j<10;j++)
{
for(int k = 0;k<10;k++)
{
if(abs(j-k)>=m)
dp[i][j]+=dp[i-1][k];
}
}
}
}
int find(int x)
{
int a[15], t = 0;
int ans = 0;
memset(a, 0, sizeof(a));
while(1)
{
a[++t] = x%10;
x/=10;
if(x == 0)
break;
}
for(int i = 1;i<t;i++)
{
for(int j = 1;j<10;j++)
ans+=dp[i][j];
}
for(int i = 1;i<a[t];i++)
ans+=dp[t][i];
for(int i = t-1;i>=1;i--)
{
for(int j = 0;j<a[i];j++)
{
if(abs(j-a[i+1])>=m)
ans+=dp[i][j];
}
if(abs(a[i]-a[i+1])<m)
break;
}
return ans;
}
int main()
{
int cas;
scanf("%d", &cas);
while(cas--)
{
memset(dp, 0, sizeof(dp));
int u, v;
scanf("%d%d%d", &u, &v, &m);
pre();
printf("%d\n", find(v+1)-find(u));
}
return 0;
}