codeforces 55D 数位DP

codeforces 55D


题意:

给 定 区 间 [ l , r ] , 限 制 条 件 : 给定区间[l,r],限制条件: [l,r]

  • 该 数 能 被 任 意 数 位 上 不 为 0 的 数 整 除 该数能被任意数位上不为0的数整除 0

问 区 间 内 满 足 以 上 条 件 的 数 的 个 数 。 问区间内满足以上条件的数的个数。


题解:

首 先 将 由 1 — 9 中 若 干 数 字 的 l c m 的 个 数 离 散 化 为 2 8 。 首先将由1—9中若干数字的lcm的个数离散化为2^8。 19lcm28
d p [ p o s ] [ l c m ] [ n u m ] b 表 示 查 找 到 第 p o s 位 , 截 止 当 前 位 的 所 有 数 的 最 小 公 倍 数 为 l c m , dp[pos][lcm][num]b表示查找到第pos位,截止当前位的所有数的最小公倍数为lcm, dp[pos][lcm][num]bposlcm
截 止 当 前 位 的 数 对 2520 ( 1 — 9 的 l c m ) 取 模 后 的 值 为 n u m 的 合 法 数 的 个 数 。 截止当前位的数对2520(1—9的lcm)取模后的值为num的合法数的个数。 252019lcmnum

  • d f s ( p o s − 1 , i &lt; 2 ? l c m : ( l c m ∣ ( 1 &lt; &lt; ( i − 2 ) ) ) , ( n u m ∗ 10 + i ) dfs(pos-1, i &lt; 2 ? lcm : (lcm|(1&lt;&lt;(i-2))), (num*10+i)%2520, limit &amp;&amp; i == bit[pos]) dfs(pos1,i<2?lcm:(lcm(1<<(i2))),(num10+i)

#include <bits\stdc++.h>
using namespace std;
typedef long long ll;
int bit[20];
ll dp[20][1<<8][2520];

ll dfs(int pos, int lcm, int num, bool limit){
    if(pos == 0){
        for(int i = 2 ; i <= 9 ; i++){
            if(lcm&(1<<(i-2)) && num%i != 0){
                return 0;
            }
        }
        return 1;
    }
    if(!limit && dp[pos][lcm][num] != -1){
        return dp[pos][lcm][num];
    }
    int up = (limit ? bit[pos] : 9);
    ll res = 0;
    for(int i = 0 ; i <= up ; i++){
        res += dfs(pos-1, i < 2 ? lcm : (lcm|(1<<(i-2))), (num*10+i)%2520, limit && i == bit[pos]);
    }
    if(!limit){
        dp[pos][lcm][num] = res;
    }
    return res;
}

ll count(ll x){
    int len = 0;
    while(x){
        bit[++len] = x%10;
        x /= 10;
    }
    return dfs(len, 0, 0, true);
}

int main() {
    int t;
    memset(dp, -1, sizeof(dp));
    for(cin >> t ; t > 0 ; t--){
        ll l, r;
        cin >> l >> r;
        cout << count(r)-count(l-1) << endl;
    }
    return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值