题意:求出l到r中,能整除自己各非0位的和的数有多少个。

转换一下,就相当于求整除自己各非0位的最小公倍数,然后1到9公倍数范围是1到2520,会爆内存,考虑离散化。

转移过程有两种,一种是非0的,一种是数位是0的,是0的话最小公倍数不变,否则最小公倍数跟新的数求一下最小公倍数。
然后mod要一直取余2520,防止数组越界。

//多少个数能够整除自身各位数
//相当于 多少个数能够整除自身各位数的最小公倍数
#include <iostream>
#include <algorithm>
#include <string.h>
#include <set>
using namespace std;
__int64 f[20][2521][50];
__int64 num[] = { 1,2,3,4,5,6,7,8,9,10,
12,14,15,18,20,21,24,28,30,35,
36,40,42,45,56,60,63,70,72,84,
90,105,120,126,140,168,180,210,252,280,
315,360,420,504,630,840,1260,2520 };
int a[20];
__int64 gcd(__int64 a, __int64 b)
{
    return b == 0 ? a : gcd(b, a % b);
}
__int64 lc(__int64 a, __int64 b)
{
    return a * b / gcd(a, b);
}
__int64 dp(__int64 pos, __int64 mod, __int64 lcm, bool flag)
{
    if (pos == 0) return mod % lcm == 0;
    __int64 tmp = lower_bound(num, num + 48, lcm) - num;
    if (flag && f[pos][mod][tmp] != -1) return f[pos][mod][tmp];
    int x = flag ? 9 : a[pos];
    __int64 ans = 0;
    for (int i = 0; i <= x; i++)
    {
        if (i == 0) ans += dp(pos - 1, (mod * 10 + i) % 2520, lcm, flag || i < x);
        else ans += dp(pos - 1, (mod * 10 + i) % 2520, lc(lcm, i), flag || i < x);
    }
    if (flag) f[pos][mod][tmp] = ans;
    return ans;
}
__int64 cul(__int64 x)
{
    int pos = 0;
    while (x)
    {
        a[++pos] = x % 10;
        x /= 10;
    }
    return dp(pos, 0, 1, false);
}
int main() 
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    memset(f, -1, sizeof(f));
    while (t--)
    {
        __int64 l, r;
        cin >> l >> r;
        cout << cul(r) - cul(l - 1) << endl;
    }
}

搞出num数组的方法,用下面这个程序输出的结果往上面拷贝

#include <iostream>
#include <algorithm>
#include <string.h>
#include <set>
using namespace std;
set <int> st;
int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}
int lc(int a, int b)
{
    return a * b / gcd(a, b);
}
int main() 
{
    for (int i = 0; i < (1 << 9); i++)
    {
        int ans = 1;
        int ii = i;
        for (int j = 1; j <= 9; j++)
        {
            if (ii & 1) ans = lc(ans, j);
            ii >>= 1;
        }
        st.insert(ans);
    }
    int i = 0;
    for (set<int>::iterator it = st.begin(); it != st.end(); it++)
    {
        cout << *it << ",";
        i++;
        if (i % 10 == 0) cout << endl;
    }
}