codeforces 55D 数位dp 记忆化搜索 lcm

要求:一个可被自身每一位的数整除的数叫做美丽数,输出[a,b]内美丽数的个数。

方法:数位dp 记忆化搜索 lcm(最小公倍数)

1.dp[i][j][k]表示i位数、模2520为j、每位上数的最小公倍数为k 的个数。1~9相乘得2520。

2.一个数可以整除自身每一位上的数,等价于可以整除自身每一位上的数的lcm。因此记录每位数的lcm即可。可将此位添加后模2520并传递到下一层,因为传递模2520与传递原数在最后模lcm的数一样。

3.套路记忆话搜索即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
long long dp[25][2600][50] ;
//dp[i][j][k]表示i位数 模2520为j 每位上数的最小公倍数为k 的个数 
int digit[25] ;
int index[2600] ;
void init()
{
	int i ;
	int num = 0 ;
	for(i = 1 ; i <= 2520 ; i ++)
	   if(2520 % i == 0)
	      index[i] = num ++ ;
}
int gcd(int a , int b)
{
	if(a == 0)
	   return b ;
	return gcd(b % a , a);
}
int LCM(int a , int b)
{
	return a / gcd(a,b) * b;
}
long long dfs(int len , int mod , int lcm , int lim)
{
    int i , j ;
	int mod1 ;
	int lcm1 ;
	int num ;
	long long ans = 0 ;
	if(len <= 0)
 	   return mod % lcm == 0 ;
	if(!lim && dp[len][mod][index[lcm]] != -1)
	   return dp[len][mod][index[lcm]] ;
	if(lim)
	   num = digit[len] ;
	else
	   num = 9 ;  
	for(i = 0 ; i <= num ; i ++)
	{
	  	mod1 = (mod * 10 + i) % 2520 ;
	  	if(i > 0)
	  	   lcm1 = LCM(lcm , i) ;
	  	else 
	  	   lcm1 = lcm ;
	  	ans += dfs(len - 1 , mod1 , lcm1 , lim && i == num) ;
	}   
	if(!lim) 
	   dp[len][mod][index[lcm]] = ans ;
	return ans ;
}
long long solve(long long x)
{
	  int len ;
      len = 0 ;
	  while(x)
      {
      	digit[++len] = x % 10 ;
      	x /= 10 ;
	  }
      return dfs(len , 0 , 1 , 1) ;
}
int main()
{
	int t ;
	int i , j , k ;
	long long a , b ;
	long long ans ;
	int len ;
	init() ;
	memset(dp , -1 , sizeof(dp)) ;
	scanf("%d" , &t) ;
	while(t --)
    {
      cin >> a >> b ;
      ans = solve(b) - solve(a - 1) ;
      cout << ans << endl ;
	}
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值