HDU 2089 不要62
int dp[10][2];
//dp[i][0]表示当前到哪一位,且前一位不是6
//dp[i][1]表示当前到哪一位,且前一位是6
int a[20];
LL dfs(int pos,bool six,bool limit){
//pos搜到的位置(从高位到低位),lead判断是否有前导零,limit判断是否有最高位限制
int ans = 0;
if (pos == -1) return 1;
//搜到最底部,此时数字为个位数并且跳过了4,满足题意,算1个
if (!limit && dp[pos][six] != -1) return dp[pos][six];
//如果没有最高位限制且要用到的dp数组已经更新过,直接返回这个结果
int end = limit ? a[pos] : 9;
//决定第pos位所能遍历的数字范围
//如果有最高位限制,则第pos位数字范围最多到原数字的第pos位数字(如原数字4521,不能算出5xxx来)
//(注意:虽然拆分数字的时候将各个数位倒着储存了,但dfs时也是倒着来的,两者方向其实一致,所以取的是a[pos])
for (int i = 0; i <= end; i++) {
if (i == 4 || six && i == 2) continue;
//这一位是4,跳过;或者前一位是6且这一位是2,构成62,跳过
ans += dfs(pos - 1, i == 6, limit && i == end);
//搜低位的dp结果,如果当前有最高位限制且这一位的数字已经是最大的了,则下一位也有最高位限制
//(如原数字4521,当前搜到4xxx,则接下来最多45xx,不能是46xx)
}
if (!limit) dp[pos][six] = ans;
//如果没有最高位限制,更新dp数组
return ans;
//更新dp数组并将结果返回上一层
}
LL part(LL x)//把数按位拆分
{
int len = 0;
while (x) {
a[len++] = x % 10;
//从a[0]开始,并且是倒着的
//如1234,在数组中为4321
x /= 10;
}
memset(dp, -1, sizeof dp);
return dfs(len-1,false,true);
//从len-1开始,即从x的最高位数字开始
}
int main()
{
ios::sync_with_stdio(false);
// int t; cin >> t; while (t--)
LL l, r;
while(cin>>l>>r)
{
if (!l && !r) break;
cout << part(r) - part(l-1)<<endl;
}
return 0;
}