论文:
http://hi.baidu.com/3xianbin/item/917aca907a3fb6f4291647fc
http://wenku.baidu.com/view/d2414ffe04a1b0717fd5dda8.html
其中一道题目求给定区间的所有数的k进制的各位数字的和:
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 207 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; ll x,y,n,k; ll getsum(ll pre,ll n,ll k) { ll C = pre, B = 1; for (int i = 0; i < n; ++i) { B *= k; C *= k; } B = B*n*(k - 1)/2; return B + C; } ll dfs(ll pre,ll n,ll k) { ll res = 0; if (n < k) { for (int i = 0; i <= n; ++i) { res += pre + i; } return res; } int d = 0; ll t = 1; ll tn = n; while (tn >= k) { tn /= k; t *= k; d++; } for (int i = 0; i < tn; ++i) { res += getsum(pre + i,d,k); } res += dfs(pre + tn,n - tn*t,k); return res; } int main() { while (cin>>x>>y>>k) { ll sum1 = dfs(0,y,k); ll sum2 = dfs(0,x - 1,k); cout<<sum1<<" "<<sum2<<" "<<sum1 - sum2<<endl; } return 0; }
首先贴一下数位DP的简单的模板:
记忆化搜索写的代码,很优雅,美观orz大神们..
转载别人的
int dfs(int i, int s, bool e) { if (i==-1) return s==target_s; if (!e && ~f[i][s]) return f[i][s]; int res = 0; int u = e?num[i]:9; for (int d = first?1:0; d <= u; ++d) res += dfs(i-1, new_s(s, d), e&&d==u); return e?res:f[i][s]=res; }
其中:
f为记忆化数组;
i为当前处理串的第i位(权重表示法,也即后面剩下i+1位待填数);
s为之前数字的状态(如果要求后面的数满足什么状态,也可以再记一个目标状态t之类,for的时候枚举下t);
e表示之前的数是否是上界的前缀(即后面的数能否任意填)。
for循环枚举数字时,要注意是否能枚举0,以及0对于状态的影响,有的题目前导0和中间的0是等价的,但有的不是,对于后者可以在dfs时再加一个状态变量z,表示前面是否全部是前导0,也可以看是否是首位,然后外面统计时候枚举一下位数。It depends.
于是关键就在怎么设计状态。当然做多了之后状态一眼就可以瞄出来。
注意:
不满足区间减法性质的话(如hdu 4376),不能用solve(r)-solve(l-1),状态设计会更加诡异
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
首先给出一个模板类的题目:
hdu Bomb
题意:
求小于等于n的包含“49”的数的个数
思路:
数位dp,模板
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("d.out", "w", stdout) #define ll __int64 #define M 100007 #define N 100007 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; ll dp[30][10][2]; int bit[30]; ll n; //pos 表示枚举到的位置,pre表示以pre为前缀,flag表示是否含有49,limit表示当前位置是否受限 ll dfs(int pos,int pre,int flag,int limit) { if (pos == -1) return flag; if (!limit && dp[pos][pre][flag] != -1) return dp[pos][pre][flag]; ll ans = 0; int up = limit? bit[pos]:9; for (int i = 0; i <= up; ++i) { int tflag = flag; if (pre == 4 && i == 9) tflag = 1; int tpre = i; ans += dfs(pos - 1,tpre,tflag,(limit && i == up)); } if (!limit) dp[pos][pre][flag] = ans; return ans; } ll solve(ll n) { int pos = 0; while (n) { bit[pos++] = n%10; n /= 10; } return dfs(pos - 1,0,0,1); } int main() { int T; scanf("%d",&T); while (T--) { CL(dp,-1); scanf("%I64d",&n); printf("%I64d\n",solve(n)); } return 0; }
题解:http://www.cnblogs.com/E-star/p/3143237.html
CF Codeforces Beta Round #51 D. Beautiful numbers
题意:
求给定区间内[l,r]的数满足被他自身所有非0数整除的数的个数
思路:
转载:
一个数字要被它的所有非零位整除,即被他们的LCM整除,可以存已有数字的Mask,但更好的方法是存它们的LCM{digit[i]}
int MOD = LCM{1,2,9} = 5 * 7 * 8 * 9 = 2520
按照定义,数字x为Beautiful :
x % LCM{digit[xi]} = 0
即 x % MOD % LCM{digit[xi]} = 0
所以可以只需存x % MOD,范围缩小了
而在逐位统计时,假设到了pre***(pre指前面的一段已知的数字,而*是任意变)
( preSum * 10^pos + next ) % MOD % LCM(preLcm , nextLcm)
= ( preSum * 10 ^ pos % MOD + next % MOD ) % LCM(preLcm , nextLcm)
== 0
而next,nextLcm是变量,上面的比较式的意义就是
在已知pos , preSum , preLcm情况下有多少种(next,nextLcm)满足式子为0
而这个就是一个重复子问题所在的地方了,需要记录下来,用记忆化搜索
dfs(pos , preSum , preLcm , doing)
加一个标记为doing表示目前是在计算给定数字的上限,还是没有上限,即***类型的
这样就将初始化以及逐位统计写在一个dfs了,好神奇!!!
还有一点,10以内的数字情况为2^3 , 3^2 , 5 , 7
所以最小公倍数组合的情况只有4*3*2*2 = 48
(我理解的最小公倍数的组和其实就2520的因子的个数)
可以存起来,我看NotOnlySuccess的写法是
for(int i = 1 ; i <= MOD ; i ++)
{
if(MOD % i == 0)
index[i] = num++;
}
很棒!!
所以复杂度大概为19*2520*48*10(状态数*决策数)
我觉得这题状态的设计不能跟具体数字分开,否则会很难设计吧
所以用记忆化搜索,存起来
用具体数字去计算,重复的子问题跟pre关系比较密切
有一个比较重要的切入点就是LCM,还有%MOD缩小范围,才能存储
还有优化到只需%252的,更快
不过我觉得%2520比较好理解
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 27 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; const int MOD = 2520; int bit[N]; ll dp[N][2527][50]; int idx[2527]; void init() { int num = 0; for (int i = 1; i <= 2520; ++i) { if (MOD % i == 0) { idx[i] = num++; } } } int gcd(int a,int b) { if (b == 0) return a; return gcd(b,a%b); } int LCM(int a,int b) { return (a*b)/gcd(a,b); } ll dfs(int pos,int pre,int lcm,int limit) { if (pos == -1) return pre%lcm == 0; if (!limit && dp[pos][pre][idx[lcm]] != -1) return dp[pos][pre][idx[lcm]]; int end = limit? bit[pos]:9; ll ans = 0; for (int i = 0; i <= end; ++i) { int tpr = (pre*10 + i)%MOD; int tlcm = lcm; if (i) tlcm = LCM(tlcm,i); ans += dfs(pos - 1,tpr,tlcm,(limit && i == end)); } if (!limit) dp[pos][pre][idx[lcm]] = ans; return ans; } ll solve(ll n) { int pos = 0; while (n) { bit[pos++] = n%10; n /= 10; } return dfs(pos - 1,0,1,1); } int main() { int T; ll l,r; CL(dp,-1); init(); cin>>T; while (T--) { cin>>l>>r; cout<<solve(r) - solve(l - 1)<<endl; } return 0; }
hdu 352 B-number
题意:
求[1,n]内满足包含13并且能被13整除的数的个数。
思路:
典型的数位统计,只不过自己在设计状态的时候没有考虑完全才开始设计成dp[pos][pres][flag]了,结果输出总是偏多,肯定是限制考虑不全全面了,首先假设我们枚举的到了第二位
31*** 和 22*** 可能后边会存在3这样的话pos = 2 pres = 4,flag = 0 是的情况就不同了,所以我们要记录一下前一个数是什么才能保证数据的正确性。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 27 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int bit[N]; ll dp[N][12][15][2]; ll n; ll dfs(int pos,int pren,int pres,int flag,int limit) { if (pos == -1) return (pres%13 == 0 && flag); if (!limit && dp[pos][pren][pres][flag] != -1) return dp[pos][pren][pres][flag]; int end = limit? bit[pos]:9; ll ans = 0; for (int i = 0; i <= end; ++i) { int tpres = (pres*10 + i)%13; int tflag = flag; if (pren == 1 && i == 3) tflag = 1; ans += dfs(pos - 1,i,tpres,tflag,(limit && i == end)); } if (!limit) dp[pos][pren][pres][flag] = ans; return ans; } ll solve(ll n) { int pos = 0; while (n) { bit[pos++] = n%10; n /= 10; } return dfs(pos - 1,0,0,0,1); } int main() { // Read(); CL(dp,-1); while (~scanf("%I64d",&n)) { cout<<solve(n)<<endl; } return 0; }
题意:
给定一个区间求该区间[L,R]内平衡数的个数,平衡数的定义:4139 存在一个数3 4*2 + 1*1 = 9*1
思路:
若某一个数是平衡数,那么它的中心是唯一确定的,我们只要设计好状态,然后枚举中间,在进行数位同,在中心轴确定的情况下该区间的数量然后求和即可。
dp[pos][d][pre] d表示中心的位置。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 27 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int bit[25]; ll dp[20][20][2000]; ll dfs(int pos,int d,int pre,int limit) { if (pos == -1) return pre == 0; if (!limit && dp[pos][d][pre] != -1) return dp[pos][d][pre]; ll ans = 0; int end = limit? bit[pos] : 9; for (int i = 0; i <= end; ++i) { int tpre = pre; tpre += (pos - d)*i; ans += dfs(pos - 1,d,tpre,(limit && i == end)); } if (!limit) dp[pos][d][pre] = ans; return ans; } ll solve(ll n) { int pos = 0; while (n) { bit[pos++] = n%10; n /= 10; } ll ans = 0; for (int i = 0; i < pos; ++i) ans += dfs(pos - 1,i,0,1); return ans - (pos - 1); } int main() { // Read(); int T; ll x,y; cin>>T; CL(dp,-1); while (T--) { cin>>x>>y; cout<<solve(y) - solve(x - 1)<<endl; } return 0; }
还存在另一种解法:
间分解:[X, Y] = [0, Y] - [0, X-1]
对于小于X的数,我们需要判定它是不是balance数:
digit(i)表示数的第i个数字
数字和:sdig=sum(digit(i)) {i=1..n }
数字位权和:snum=sum(i*digit(i)) {i=1..n}
每一次判断数是不是平衡的,就看snum%sdig是不是0.
我们首先假设中间值在最高为的左边 4139 在4的左边,我们倒着将数取出来之后在-1位置,当我们将中间值向右移动时每次多的一边会减少sdig
// BEGIN CUT HERE // END CUT HERE #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 5007 #define N 1007 using namespace std; ll dp[20][170][2000]; int bit[20]; //位置,数字和,加权和,是否有限制 ll dfs(int pos,int sd,int s,int limit) { if (pos == -1) return sd == 0 || s%sd == 0; if (!limit && dp[pos][sd][s] != -1) return dp[pos][sd][s]; int end = limit? bit[pos] : 9; ll ans = 0; for (int i = 0; i <= end; ++i) { int tsd = sd + i; int ts = s + pos*i; ans += dfs(pos - 1,tsd,ts,limit && i == end); } if (!limit) dp[pos][sd][s] = ans; return ans; } ll solve(ll n) { int pos = 0; while (n) { bit[pos++] = n%10; n /= 10; } return dfs(pos - 1,0,0,1); } int main() { int T; ll x,y; cin>>T; CL(dp,-1); while (T--) { cin>>x>>y; cout<<solve(y) - solve(x - 1)<<endl; } return 0; }
题意:
中文...
思路:
这道题目的难度还是不好想的,关键在于平方和的维护。
我们首先求出整个区间[0,R]的所有数的平方和,然后见去与7有关的平方和即可。 如何求该区间与7有关的平方和呢。 要是求该区间的个数的话,就很简单了。模板就可。
我们假设我们枚举的当前位为pos位,且在该位的数子是i,后缀满足的个数为n, 所有后缀的平方和为k1^2 + k2^2 + ... + kn^2; 那么我们 ki为后缀这个数。
则x = i*10^(cnt - 1);
那么此时满足的平方和为 (i*x + k1)^2 + (i*x + k2)^2 + ... (i*x + kn)^2 展开后的:
n*(i*x)^2 + 2*i*x*(k1 + k2 + ... + kn) + (k1^2 + k2^2 + ..... + kn^2); 由此我们可以发现,如果要得到满足条件的平方和,我们维护三个部分,后缀满足的个数n,所有满足条件的后缀的和,所有满足条件的后缀的平方和。
还要用到一个数学公式 :1^2 + 2^2 + 3^2 + ... + n^2 = n*(n + 1)*(2*n + 1)/6;
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 27 using namespace std; const int inf = 0x7f7f7f7f; const ll mod = 1000000007; struct node { ll cnt;//后缀满足的个数 ll sum1;//所有满足条件的后缀的和 ll sum2;//所有满足条件的后缀的平方和。 void init() { cnt = sum1 = sum2 = 0; } void install() { cnt = sum1 = sum2 = -1; } }dp[N][10][10][2]; ll fac[N]; int bit[N]; node dfs(int pos,int a,int b,int c,int limit) { if (pos == 0) { dp[pos][a][b][c].init(); if (a && b && !c) dp[pos][a][b][c].cnt = 0; else dp[pos][a][b][c].cnt = 1; return dp[pos][a][b][c]; } if (!limit && dp[pos][a][b][c].cnt != -1) return dp[pos][a][b][c]; int end = limit? bit[pos - 1] : 9; node ans; ans.init(); for (int i = 0; i <= end; ++i) { int ta = (a*10 + i)%7; int tb = (b + i)%7; int tc = c; if (i == 7) tc = 1; node tmp = dfs(pos - 1,ta,tb,tc,limit && i == end); //关键是这里的计算n*(i*x)^2 + 2*i*x*(k1 + k2 + ... + kn) + (k1^2 + k2^2 + ..... + kn^2); ll x = i*fac[pos - 1]%mod; ans.cnt = (ans.cnt + tmp.cnt)%mod; ans.sum1 =((ans.sum1 + tmp.sum1)%mod + tmp.cnt*x%mod)%mod; ans.sum2 = (((ans.sum2 + tmp.cnt*x%mod*x%mod)%mod + tmp.sum2)%mod + 2*tmp.sum1*x%mod)%mod; } return limit ? ans : dp[pos][a][b][c] = ans; } ll SUM(ll m) { ll a = m,b = m + 1,c = 2*m + 1; int x = 3,y = 2; //肯定能够把x和y除了 if (a%x == 0) a /= x,x = 1; if (a%y == 0) a /= y, y = 1; if (b%x == 0) b /= x,x = 1; if (b%y == 0) b /= y, y = 1; if (c%x == 0) c /= x,x = 1; if (c%y == 0) a /= y, y = 1; a %= mod; b %= mod; c %= mod; return a*b%mod*c%mod; } ll solve(ll n) { int pos = 0; ll m = n; while (n) { bit[pos++] = n%10; n /= 10; } return (SUM(m) - dfs(pos,0,0,0,1).sum2 + mod)%mod; } void init() { fac[0] = 1; for (int i = 1; i <= 20; ++i) { fac[i] = fac[i - 1]*10%mod; } for (int i = 0; i <= 20; ++i) { for (int j = 0; j < 7; ++j) { for (int k = 0; k < 7; ++k) { for (int p = 0; p < 2; ++p) { dp[i][j][k][p].install(); } } } } } int main() { // Read(); init(); int T; cin>>T; ll x,y; while (T--) { cin>>x>>y; cout<<(solve(y) - solve(x - 1) + mod)%mod<<endl; } return 0; }
fzu 2113 Jason的特殊爱好
题意: 中文
思路:
当我们枚举完后缀时,价差一下最高为是否为1,如果为1的话,在看当前为是否有限,如果有限的话,就只能加上后缀 + 1了,如果无线的话就是0 -- 9999***了
例如 331454 假设我们枚举到了21****这时是没有限制的那么我们就可以加上9999 +1个了,如果枚举到了331***我们只能加454了
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 5007 #define N 1007 using namespace std; ll dp[20][10]; int bit[20]; ll fac[20],s[20]; ll dfs(int pos,int lt,int lm) { if (pos == -1) return lt == 1; if (!lm && dp[pos][lt] != -1) return dp[pos][lt]; int end = lm? bit[pos] : 9; ll ans = 0; for (int i = 0; i <= end; ++i) { ans += dfs(pos - 1,i,lm && i == end); } if (lt == 1) { if (!lm) ans += fac[pos + 1]; else ans += s[pos] + 1; } return lm ? ans : dp[pos][lt] = ans; } ll solve(ll n) { int pos = 0; ll m = n; while (n) { // cout << n << endl; bit[pos] = n%10; n /= 10; s[pos] = m%fac[pos + 1];//把我们需要的后缀取出来 pos++; } return dfs(pos - 1,0,1); } void init() { fac[0] = 1; for (int i = 1; i < 20; ++i) fac[i] = fac[i - 1]*10; CL(dp,-1); } int main() { // Read(); ll x,y; init(); while (cin>>x>>y) { cout<<solve(y) - solve(x - 1)<<endl; } return 0; }