列表

详情


NC20287. [SCOI2012]BLINKER的仰慕者

描述

Blinker 有非常多的仰慕者,他给每个仰慕者一个正整数编号。
而且这些编号还隐藏着特殊的意义,即编号的各位数字之积表示这名仰慕者对Blinker的重要度。
现在Blinker想知道编号介于某两个值A,B之间,且重要度为某个定值K的仰慕者编号和。

输入描述

输入的第一行是一个整数N,表示Blinker想知道的信息个数。
接下来的N行,每行有三个数,A,B,K。表示 Blinker想知道编号介于A和B之间的, 重要度为K的仰慕者的编号和。

输出描述

输出N行,每行输出介于A和B之间,重要度为 K的仰慕者编号和。结果可能很大, 模上20120427。

示例1

输入:

3 
1 14 4 
1 30 4 
10 60 5

输出:

18
40
66

说明:

【样例解释】
第一组样例中,在 1到14之间各位数字之积等于 4的有 4和 14,故编号和为18。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 281ms, 内存消耗: 5376K, 提交时间: 2021-10-23 14:17:53

#include<cstdio>
#include<map>
typedef long long LL;
std::map<LL, int>m;
const int N = 5e4, P = 20120427;
int pw[21], bit[21], g[21][N], f[21][N], af[21], ag[21], tp, L;
long long K, st[N];
void Up(int &a, int b) {a += b; if(a >= P) a -= P;}
void Pre() {
    pw[0] = 1; for(int i = 1;i <= 20; ++i) pw[i] = pw[i - 1] * 10 % P;
    for(int i = 0;i <= 9; ++i) {
        m[i] = ++tp; st[++L] = i;
        f[1][tp] = 1; g[1][tp] = i;
    }
    for(int i = 1, nL = L;i <= 18; ++i, L = nL)
        for(int j = 1;j <= L; ++j) {
            LL x = st[j]; int pr = m[x];
            for(int k = 0;k <= 9; ++k) {
                if(!m[x * k]) st[++nL] = x * k, m[x * k] = ++tp; 
                int nx = m[x * k]; Up(f[i + 1][nx], f[i][pr]);
                Up(g[i + 1][nx], (1LL * f[i][pr] * pw[i] * k + g[i][pr]) % P);
            }
        }
    for(int i = 1;i < 20; ++i)
        for(int j = 1;j <= L; ++j)
            Up(af[i], f[i][j]), Up(ag[i], g[i][j]);
}
int Dfs0(int i, int s, bool Z, bool e, bool z) {
    if(!i) return Z ? s : 0;
    if(!e && !z) {
        int A = !Z ? f[i][1] : af[i], B = !Z ? g[i][1] : ag[i];
        return (1LL * s * A % P * pw[i] + B) % P;
    }
    int end = e ? bit[i] : 9, r = 0;
    for(int v = 0;v <= end; ++v) 
        Up(r, Dfs0(i - 1, (s * 10 + v) % P, Z | !v & !z, e && (v == end), z && !v));
    return r;
}
int Dfs(int i, int s, LL K, bool e, bool z) {
    if(!i) return K == 1 ? s : 0;
    int t = m[K]; if(!t) return 0;
    if(!e && !z) return (1LL * s * f[i][t] % P * pw[i] + g[i][t]) % P;
    int end = e ? bit[i] : 9, r = 0;
    if(z) Up(r, Dfs(i - 1, s, K, e && !end, 1));
    for(int v = 1;v <= end; ++v) 
        if(!(K % v)) Up(r, Dfs(i - 1, (s * 10 + v) % P, K / v, e && (v == end), 0));
    return r;
}
int Cal(long long x) {
    int tp = 0; for(;x; x /= 10) bit[++tp] = x % 10;
    if(K != 0) return Dfs(tp, 0, K, 1, 1);
    else return Dfs0(tp, 0, 0, 1, 1);
}
int main() {
    Pre();
    int T; for(scanf("%d", &T); T--; ) {
        LL A, B; scanf("%lld%lld%lld", &A, &B, &K);
        printf("%d\n", (Cal(B) - Cal(A - 1) + P) % P);
    }
    return 0;
}

上一题