[CF96E] Horse Races - 数位dp
Description
给定区间 ([l,r]),求区间内有多少个数满足其中存在幸运数字,并且至少有两个幸运数字相差的位数不超过 (k)
Solution
数位 dp,设 (f(pos,lim,last,flag)) 表示从高到低处理到了第 (pos) 位,当前是否顶格,上一位幸运数字在 (last) 位置,当前是否已经满足条件
转移的时候,对于当前位是幸运数字和不是幸运数字的情况,分别处理即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
int a[1005], f[1005][2][2005][2], n, k;
int dfs(int pos, int lim, int last, int flag)
{
if (pos < 0)
{
return flag;
}
auto &ans = f[pos][lim][last][flag];
if (~ans && !lim)
return ans;
ans = 0;
int up = lim ? a[pos] : 9;
for (int i = 0; i <= up; i++)
{
if (i == 4 || i == 7)
{
ans += dfs(pos - 1, lim && (i == a[pos]), pos, flag || (last - pos <= k));
}
else
{
ans += dfs(pos - 1, lim && (i == a[pos]), last, flag);
}
ans %= mod;
}
return ans;
}
int solve(int flag)
{
string str;
cin >> str;
for (int i = 0; i < str.size(); i++)
a[str.size() - 1 - i] = str[i] - '0';
int res = 0;
if (flag)
{
set<int> s;
for (int i = 0; i < str.size(); i++)
if (str[i] == '4' || str[i] == '7')
s.insert(i);
for (auto i : s)
{
auto t = s.upper_bound(i);
if (t != s.end())
if (*t - i <= k)
res = 1;
}
}
return (dfs(str.size() - 1, 1, str.size() + k, 0) - res + mod) % mod;
}
void group()
{
int a1 = solve(1);
int a2 = solve(0);
cout << (a2 - a1 + mod) % mod << endl;
}
signed main()
{
ios::sync_with_stdio(false);
memset(f, -1, sizeof f);
int t;
cin >> t >> k;
while (t--)
group();
}