题意:找出l,r之间的符合至少有幸运数字相差不超过k的数的个数。
思路:明显的数位dp.思路很简单。但是一直WA在第16个测试样例,因为pre刚开始设置为k + len,想着这样能保证第一个与他相减能使得不低于k,然而pre作为dp数组里的记忆话的元素,并不能频繁地改变,长记性了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define clr(x,y) memset(x,y,sizeof x)
const int maxn = 1000 + 10;
const int Mod = 1e9 + 7;
const int N = 2;
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pass System Test!
*/
string s1,s2;
int bits[maxn];
int n,k;
ll dp[maxn][1010][2];
ll dfs(int pos,bool flags,int pre,bool flag)
{
if(pos < 0)return flags;
if(!flag && dp[pos][pre][flags] != -1)return dp[pos][pre][flags];
int up = flag ? bits[pos] : 9;
ll ret = 0;
for(int i = 0; i <= up; i ++)
{
if(i == 4 || i == 7)
{
ret = (ret + dfs(pos - 1,flags ||(pre != -1 && (abs(pre - pos) <= k) ),pos,flag && i == up)) % Mod;
}
else ret = (ret + dfs(pos - 1,flags,pre,flag && i == up) ) % Mod;
}
if(!flag )dp[pos][pre][flags] = ret;
return ret;
}
ll calc(string t)
{
int len = 0;for(int i = t.size() - 1; i >= 0; i --)bits[len ++] = t[i] - '0';
return dfs(len - 1,false,-1,true);
}
int main()
{
clr(dp,-1);
// freopen("out.txt","r",stdin);
while( ~ scanf("%d%d",&n,&k))
{
for(int i = 1; i <= n; i ++)
{
cin >> s1 >> s2;int flag = 0;int len = s1.size(),temp = -k - 2;
for(int i = 0; i < len; i ++)
if(s1[i] == '4' || s1[i] == '7')
{if(abs(i - temp) <= k ){flag = 1;break;}else temp = i;}
// cout << calc(s1) << " " << calc(s2) << " " << flag << endl;
printf("%I64d\n", ((calc(s2) - calc(s1) + flag) % Mod + Mod) % Mod);
}
}
return 0;
}