1 条题解

  • 0
    @ 2026-5-5 23:26:14

    数位 dp。差分一下,记 xx 每一位构成的序列为 xix_i。我们考虑将这个问题转化成用拼成的数与 xix_i 匹配,记 fl,r,i,j,0/1/2f_{l,r,i,j,0/1/2} 表示 alra_{l\cdots r} 中选出了 ji+1j-i+1 个数,且与 xijx_{i\cdots j} 的大小关系(小于/等于/大于)。那么我们可以把 ara_r 接在前面:

    • ar<bi,fl,r,i,j,0fl,r1,i+1,j,ka_r<b_i, f_{l,r,i,j,0}\leftarrow f_{l,r-1,i+1,j,k}
    • ar=bi,fl,r,i,j,kfl,r1,i+1,j,ka_r=b_i, f_{l,r,i,j,k}\leftarrow f_{l,r-1,i+1,j,k}
    • ar>bi,fl,r,i,j,2fl,r1,i+1,j,ka_r>b_i, f_{l,r,i,j,2}\leftarrow f_{l,r-1,i+1,j,k}

    也可以接在后面:

    • fl,r,i,j,0fl,r1,i,j1,0f_{l,r,i,j,0}\leftarrow f_{l,r-1,i,j-1,0}
    • fl,r,i,j,tfl,r1,i,j1,1f_{l,r,i,j,t}\leftarrow f_{l,r-1,i,j-1,1},其中 ttara_rbjb_j 的大小关系
    • fl,r,i,j,2fl,r1,i,j1,2f_{l,r,i,j,2}\leftarrow f_{l,r-1,i,j-1,2}

    边界:fl,r,i,i,tfl,r1,i,i,t+2f_{l,r,i,i,t}\leftarrow f_{l,r-1,i,i,t}+2 其中 ttara_rbib_i 的大小关系(因为可以在前面/后面添加 ara_r

    答案:$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}$

    最后对 fl,rf_{l,r} 滚动即可。

    :::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
    上传者