# [hdu2089]不要62 题解
[hdu2089]不要62 题解
鸽的有点久了
某蒟蒻开始学计数dp了
思路
设 \(f_{i,1/0}\) 为前i个数位,前一位是否为 \(6\) 的合法数量
然后用dfs考虑每一个数位的取值,注意不要超过 \(R\) 上限
其中用一下记忆化
区间用前缀和求解
code
有点弱智偏xxs的马蜂
#include<bits/stdc++.h>
#define int long long
using namespace std;
int f[10][2];//f[i][j]:前i个数位,前一位是不是6
int l,r,a[10];//a数组存R的上限,即各位数字
//目前是第x位,v6判断前一位是否是6,pd判断是否为上界
int dfs(int x,bool v6,bool pd)
{
if(!x) return 1;//选完了,这个数可以,计算答案贡献
if(!pd&&f[x][v6]>-1) return f[x][v6];//记忆化
int lim=pd?a[x]:9;//判断上界,如果这一位前面的都是上界,那么这一位不能超过R的这一位
int ans=0;
for(int i=0;i<=lim;i++)
{
if(i==4||(v6&&i==2)) continue;//不符合条件,即有62或4
ans+=dfs(x-1,i==6,pd&&(i==a[x]));
}
if(!pd) f[x][v6]=ans;
return ans;
}
int solve(int R)//处理上限,然后计算答案
{
int cnt=0;
while(R)
{
a[++cnt]=R%10;
R/=10;
}
return dfs(cnt,0,1);
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
while(cin>>l>>r)
{
if(!l&!r) exit(0);
memset(f,-1,sizeof f);
cout<<solve(r)-solve(l-1)<<"\n";
}
}