1 条题解
-
0
数位 dp。差分一下,记 每一位构成的序列为 。我们考虑将这个问题转化成用拼成的数与 匹配,记 表示 中选出了 个数,且与 的大小关系(小于/等于/大于)。那么我们可以把 接在前面:
也可以接在后面:
- ,其中 是 与 的大小关系
边界: 其中 是 与 的大小关系(因为可以在前面/后面添加 )
答案:$ans_{l,r}=f_{l,r,1,m,0}+f_{l,r,1,m,1}+\sum\limits_{i\geq 2}f_{l,r,i,m,2}$
最后对 滚动即可。
:::success[代码]
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 505, M = 20, p = 1e9 + 7; int n, m, q, a[N], b[N], f[M][M][3], ans[2][N][N]; void Init(ll x) { m = 0; while(x) b[++m] = x % 10, x /= 10; reverse(b + 1, b + m + 1); } void Solve(ll x, bool tp) { Init(x); for(int l = 1; l <= n; l++) { memset(f, 0, sizeof(f)); for(int r = l; r <= n; r++) { for(int i = 1; i <= m; i++) { for(int j = m; j > i; j--) { if(a[r] > b[i]) for(int k = 0; k < 3; k++) (f[i][j][2] += f[i+1][j][k]) %= p; else if(a[r] == b[i]) for(int k = 0; k < 3; k++) (f[i][j][k] += f[i+1][j][k]) %= p; else for(int k = 0; k < 3; k++) (f[i][j][0] += f[i+1][j][k]) %= p; (f[i][j][0] += f[i][j-1][0]) %= p, (f[i][j][2] += f[i][j-1][2]) %= p; int t = (a[r] == b[j] ? 1 : (a[r] > b[j]) * 2); (f[i][j][t] += f[i][j-1][1]) %= p; } } for(int i = 1; i <= m; i++) { int t = (a[r] == b[i] ? 1 : (a[r] > b[i]) * 2); (f[i][i][t] += 2) %= p; } for(int i = 1; i <= m; i++) for(int k = 0; k < 3; k++) if(i != 1 || k != 2) (ans[tp][l][r] += f[i][m][k]) %= p; } } } int main() { ll A, B; scanf("%d%lld%lld", &n, &A, &B); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); scanf("%d", &q); Solve(B, 1); Solve(A - 1, 0); while(q--) { int l, r; scanf("%d%d", &l, &r); printf("%d\n", ((ans[1][l][r] - ans[0][l][r]) % p + p) % p); } return 0; }
- 1
信息
- ID
- 7597
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 15
- 已通过
- 7
- 上传者