[CF55D]Beautiful numbers(数位dp,状态压缩)

题目链接:http://codeforces.com/problemset/problem/55/D

题意:给定区间,求区间内某数的所有数位能整除这个数本身的数的个数。

起初思路:dp(l,s,sum)表示这个数到l位,并且0~9出现的状态s,和为sum的时候的数字个数。发现这个sum不好处理,因为数字越来越大无法保证这个界限。用到一个性质:一个数能被一堆数整除,当且仅当这个数能被这堆数的最小公倍数整除。换句话说,我们统计这个数对1~9的最小公倍数取模,就能判断这个sum是否可以被各位数整除了。

结果MLE了,因为s这个状态统计了0~9 10个数的状态,所以占用空间是1024,因为0不用考虑,1一定能整除这个sum,所以删掉这两位。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define fr first
 4 #define sc second
 5 #define cl clear
 6 #define BUG puts("here!!!")
 7 #define W(a) while(a--)
 8 #define pb(a) push_back(a)
 9 #define Rint(a) scanf("%d", &a)
10 #define Rll(a) scanf("%I64d", &a)
11 #define Rs(a) scanf("%s", a)
12 #define Cin(a) cin >> a
13 #define FRead() freopen("in", "r", stdin)
14 #define FWrite() freopen("out", "w", stdout)
15 #define Rep(i, len) for(int i = 0; i < (len); i++)
16 #define For(i, a, len) for(int i = (a); i < (len); i++)
17 #define Cls(a) memset((a), 0, sizeof(a))
18 #define Clr(a, x) memset((a), (x), sizeof(a))
19 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
20 #define lrt rt << 1
21 #define rrt rt << 1 | 1
22 #define pi 3.14159265359
23 #define RT return
24 #define lowbit(x) x & (-x)
25 #define onecnt(x) __builtin_popcount(x)
26 typedef long long LL;
27 typedef long double LD;
28 typedef unsigned long long ULL;
29 typedef pair<int, int> pii;
30 typedef pair<string, int> psi;
31 typedef pair<LL, LL> pll;
32 typedef map<string, int> msi;
33 typedef vector<int> vi;
34 typedef vector<LL> vl;
35 typedef vector<vl> vvl;
36 typedef vector<bool> vb;
37
38 const int maxn = 25;
39 const LL mod = 2520;
40 LL dp[maxn][1<<8][mod];
41 int digit[maxn];
42
43 LL lcm(LL x, LL y) {
44   return x / __gcd(x, y) * y;
45 }
46
47 int get(int i, int s) {
48   if(i < 2) return s;
49   return s | (1 << (i-2));
50 }
51
52 LL dfs(int l, int s, int sum, bool flag) {
53   if(l == 0) {
54     For(i, 2, 10) {
55       if(((1 << (i-2))& s) && (sum % i) != 0) return 0;
56     }
57     return 1;
58   }
59   if(!flag && ~dp[l][s][sum]) return dp[l][s][sum];
60   LL ret = 0;
61   int pos = !flag ? 9 : digit[l];
62   Rep(i, pos+1) {
63     ret += dfs(l-1, get(i, s), (sum*10+i)%mod, flag&&(i==pos));
64   }
65   if(!flag) dp[l][s][sum] = ret;
66   return ret;
67 }
68
69 LL l, r;
70
71 LL f(LL x) {
72   int pos = 0;
73   while(x) {
74     digit[++pos] = x % 10;
75     x /= 10;
76   }
77   return dfs(pos, 0, 0, true);
78 }
79
80 signed main() {
81   //FRead();
82   Clr(dp, -1);
83   int T;
84   Rint(T);
85   W(T) {
86     cin >> l >> r;
87     cout << f(r) - f(l-1) << endl;
88   }
89   RT 0;
90 }
时间: 2024-10-21 16:13:47

[CF55D]Beautiful numbers(数位dp,状态压缩)的相关文章

CF55D Beautiful numbers (数位dp)

题目链接 题解 一个数能被一些数整除,那么一定被这些数的\(lcm\)整除 那么我们容易想到根据\(lcm\)设状态 我们可以发现有用的\(lcm\)只有\(48\)个 那么按照一般的数位\(dp\) 设出状态:\(f_{i,j,k,0/1}\)表示前\(i\)位,\(lcm=j\),模\(lcm\)的余数是\(k\),是否达到上界 但是这样子是无法转移的(因为新添加一个数模数可能会产生变化) 那么我们把模数统一成\(2520\) 复杂度\(O(T*L*48*2500*2)\) 其中\(L\)是

Codeforce 401D Roman and Numbers[数位DP+状态压缩]

给出数n和m,求n的所有排列中,模m得0的有多少个 n (1?≤?n?<?1018) and m (1?≤?m?≤?100). 暴力法我们直接枚举n的所有排列,显然18!超时. 考虑怎么dp 假设给了我们数n=23765 显然有 (237%m*10+6)%m=2376%m (367%m*10+2)%m=3672 我们很自然的想到了 这样的状态转移 dp[i][k] i代表取的数的状态 代表在取数状态为i的情况下模m为k的数有多少 比如 对于23765的356 取数状态为01011 dp方程就是

CF55D Beautiful numbers 数位dp

恢复魔芋本质,,改了1h+,, 题目传送门 其实这个题挺水的.也就我这种忘了%大佬的蒟蒻要调这么久. 首先,我们要找的是能被每一位整除的数.处理成1~R的答案  -  1~(l-1)的答案. 从最高位开始搜索放啥.如果已经是最后一位了,且当前数能被当前各位的最小公倍数整除,它就是一个合法的方案.那么,将长度,当前和,当前lcs,是否有限制带着搜就行了. 注意,因为每一位只有1~9,这里的不同lcs最多不到50个,预处理离散化一下即可. 还有就是本组数据结束的时候要把有限制的清空,无限制的保留(最

hdu 4352 数位dp + 状态压缩

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2265    Accepted Submission(s): 927 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

【HDU 4352】 XHXJ&#39;s LIS (数位DP+状态压缩+LIS)

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2422    Accepted Submission(s): 990 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

CodeForces 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

[数位dp+状态压缩] hdu 4352 XHXJ&#39;s LIS

题意: 给x.y.k,在[x,y] 范围内最长上升子序列长度是k的数有几个 思路: 模仿 LIS nlogn的想法,这里就只有10个数,进行状压 然后直接搜就好了不用二分 然后按位dp下去就ok了! 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"al

Codeforces Beta Round #51---D. Beautiful numbers(数位dp, 巧妙)

Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful num

CodeForces 55D Beautiful numbers(数位dp&amp;&amp;离散化)

题目链接:[kuangbin带你飞]专题十五 数位DP A - Beautiful numbers 题意 ps:第一道数位dp,题真好,虽然是参考大牛方法悟过才a,但仍收获不少. 求一个区间内的Beautiful numbers有多少个.Beautiful numbers指:一个数能整除所有组成它的非0数字. 例如15可以被1和5整除,所以15是Beautiful numbers. 思路 Beautiful numbers指:一个数能整除所有组成它的非0数字. 等同于 一个数能整除 所有组成它的

CodeForces 55D - Beautiful numbers - [数位DP+离散化]

题目链接:https://cn.vjudge.net/problem/CodeForces-55D Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with