CodeForces 288E Polo the Penguin and Lucky Numbers

洛谷传送门

CF 传送门

虚高 *2800,放模拟赛 T1 人均切了。

首先我们发现这玩意有可减性,用 [1,r] 的答案减去 [1,l] 即可。所以接下来我们只讨论前缀的情况。

考虑数位 dp。为了计算题目的那玩意我们考虑把每个状态的 dp 值用一个三元组 (a1,an,i=1n1aiai+1) 表示。那么这样是可以合并的,i=1n1aiai+1 变成两边的 i=1n1aiai+1 之和再加上左边的 an 乘上右边的 a1 即可。

但是我们发现我们还要进行让全部 ai 加上 x=t×10k 的操作。考虑 i=1n1(x+ai)(x+ai+1)=(n1)x2+xi=1n1(ai+ai+1)+i=1n1aiai+1。所以我们多维护 i=1n1ai+ai+1n 即可转移。

时间复杂度 O(log10r)

code
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 100100;
const ll mod = 1000000007;
ll a[maxn], b[maxn], n, pw[maxn];
char s[maxn], t[maxn];
bool g[maxn][2];
struct node {
ll l, r, x, y, z;
node(ll a = 0, ll b = 0, ll c = 0, ll d = 0, ll e = 0) : l(a), r(b), x(c), y(d), z(e) {}
} f[maxn][2];
inline node operator + (const node &a, const node &b) {
node res;
res.l = a.l;
res.r = b.r;
res.x = (a.x + b.x + a.r * b.l) % mod;
res.y = (a.y + b.y + a.r + b.l) % mod;
res.z = (a.z + b.z) % mod;
return res;
}
node dfs(int pos, bool lim, ll *a) {
if (pos > n) {
return node(0, 0, 0, 0, 1);
}
if (g[pos][lim]) {
return f[pos][lim];
}
g[pos][lim] = 1;
node &ans = f[pos][lim];
ll up = (lim ? a[pos] : 9);
for (ll x : {4, 7}) {
if (x > up) {
break;
}
node res = dfs(pos + 1, lim & (x == up), a);
ll t = x * pw[n - pos] % mod;
res.l = (res.l + t) % mod;
res.r = (res.r + t) % mod;
res.x = (res.x + t * t % mod * (res.z + mod - 1) + t * res.y) % mod;
res.y = (res.y + t * 2 % mod * (res.z + mod - 1)) % mod;
if (x == 4) {
ans = res;
} else {
ans = ans + res;
}
}
return ans;
}
void solve() {
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1);
pw[0] = 1;
for (int i = 1; i <= n; ++i) {
a[i] = s[i] - '0';
b[i] = t[i] - '0';
pw[i] = pw[i - 1] * 10 % mod;
}
ll ans = dfs(1, 1, b).x;
mems(g, 0);
ans = (ans - dfs(1, 1, a).x + mod) % mod;
printf("%lld\n", ans);
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
posted @   zltzlt  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示