codeforces 55D Beautiful numbers 数位dp

dp[i][lcm][mod]
i 推到第几位
lcm 为 比i高的位的值的最小公倍数,
mod为此时的数值 %(lcm(1, 2, 3, 4, 5, 6, 7, 8, 9) = 2520)的价值
dp[i][lcm][mod] 的值为这个状态时 0 - (i -1)位选择的方案数使其最后数值%所有位的lcm为0
因为2520能够整除任意由1 - 9 形成的最小公倍数所以%2520 最后判断 mod % lcm 等于0就合法 不是就不合法
要把1 - 9 形成的所有最小公倍数离散化

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#define LL long long
#define mod 2520
using namespace std;
vector<LL>ve;
LL dp[30][55][2600];
LL has[2000];
LL x[50], l;
LL gcd(LL a, LL b)
{
   while(b)
   {
       int t = a %b;
       a = b;
       b = t;
   }
   return a;
}
LL dfs(int i, bool e, int lcm, LL pre)
{
   if(i == -1)
   {
       if(pre % lcm == 0) return 1;
       else return 0;
   }
   if(e && dp[i][has[lcm]][pre % mod] != -1) return dp[i][has[lcm]][pre % mod];
   LL Max = e ? 9 : x[i], ans = 0;
   for(int j = 0; j <= Max; j++)
       if(j!=0)ans +=  dfs(i - 1, !(!e && j == x[i]), lcm * j / gcd(lcm, j), (pre * 10 + j) % mod);
       else ans += dfs(i - 1, !(!e && j == x[i]), lcm, (pre * 10 + j) % mod);
   if(e) dp[i][has[lcm]][pre] = ans;
   return ans;
}
LL cal(LL n)
{
   l = 0;
   while(n)
   {
      x[l++] = n % 10ll;
      n /= 10ll;
   }
   return dfs(l - 1, 0, 1, 0);
}
void dfs2(int pre,int i)
{
     ve.push_back(pre);
     for(int j = i; j<= 9; j++)
         dfs2(pre * j / gcd(pre, j), j + 1);
}
int main()
{
    dfs2(1,1);
    sort(ve.begin(), ve.end());
    vector<LL>::iterator it = unique(ve.begin(),ve.end());
    ve.erase(it,ve.end());
    for(int i = 0; i < ve.size(); i++) has[ve[i]] = i;
    memset(dp, -1, sizeof(dp));

    LL a, b, t;
    scanf("%I64d", &t);
    while(t--)
    {
        scanf("%I64d %I64d", &a, &b);
        printf("%I64d\n", cal(b) - cal(a - 1));
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值