CodeForces 55D Beautiful numbers

152 篇文章 0 订阅

题意:

找出L~R中所有的数字,数字和可以被每一位数字整除的总个数

思路:

1~9中,如果同时能被 比如1 3 5整除,那么一定能被最小公倍数15整除

建立HASH映射,反应在最小公倍数的情况下



    for(int i=1;i<=MOD;i++)
    {
        if(MOD%i==0)
        {
            Hash[i]=cnt++;
        }
    }

对于当前数字,在表中对应个数。

之后DP【i】 【j】 【k】

i 表示数字长度, j 表示在Hash表中所在位置,K表示目前为止所有数字和

'

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm >
using namespace std;
typedef long long ll;
int digit[20];
const int MOD = 2520;
ll dp[20][50][2550];
int Hash[2550]; 
int gcd(int x,int y)
{
    return x%y? gcd(y,x%y):y;
}
ll dfs(int len,int lcm,int have,int limit )
{
    if(!len )
    {
        if(have%lcm==0)
            return 1;
        else
                return 0;
    }
    if(!limit&&dp[len][ Hash[lcm] ][have]!=-1)
        return dp[len][ Hash[lcm] ][have];
    ll res=0;
    int maxx=limit? digit[len]:9;
    for(int i=0;i<=maxx;i++)
    {
        if(i==0)
        res+=dfs(len-1,lcm,(have*10+i)%MOD ,limit&&i==maxx);
        else
        {
            int lcm2=i*lcm/gcd(lcm,i);
            res+=dfs(len-1,lcm2, (have*10+i)%MOD, limit&&i==maxx);
        }
    }
    if(!limit)
        dp[len][Hash[lcm]][have]=res;
    return res;
}
ll solve(ll n)
{
    int len=0;
    while(n)
    {
        digit[++len]=n%10;
        n/=10;
    }
    return dfs(len,1,0,1 );
}
int main()
{
    ll n,cnt=0;
    memset(dp,-1,sizeof(dp));
    for(int i=1;i<=MOD;i++)
    {
        if(MOD%i==0)
        {
            Hash[i]=cnt++;
        }
    }
    int T;
    cin>>T;
    while(T--)
    {
        ll l, r;
        scanf("%lld%lld", &l, &r);
        printf("%lld\n", solve(r) - solve(l-1));
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值