首先带入的参数有些变化:
1. 增加了一个$k2$,代表另一个求解的数。
2. 将$cnt2$的意义改成$k2$的出现次数。
记忆化很容易写出,然后就是转移了:
由于这个数只由两个数字组成,我们不需要循环,只需要把循环展开就好了,即写两个$if$,再把计算贡献的$copy$下来就$ok$了。(不过这里要记得考虑一下$cnt2$的转移)
```
long long dfs2(long long len,long long k1,long long k2,long long cnt1,long long cnt2,long long flg1,long long flg2){
if(len==0)
return cnt1==cnt2;
if(f[len][cnt1][cnt2][flg1][flg2]!=-1)
return f[len][cnt1][cnt2][flg1][flg2];
long long res=0;
if(k1<=num[len]||flg1==0)
res+=dfs2(len-1,k1,k2,cnt1+(k1!=0||flg2==0),cnt2,k1==num[len]&&flg1,k1==0&&flg2);
if(k2<=num[len]||flg1==0)
res+=dfs2(len-1,k1,k2,cnt1,cnt2+(k2!=0||flg2==0),k2==num[len]&&flg1,k2==0&&flg2);
return f[len][cnt1][cnt2][flg1][flg2]=res;
}
```
但是交上去后发现并没有这么简单,还是WA。
为什么呢?这里我想了很久,发现前导零没有考虑:因为位数不一定,因此要考虑前导零的转移(记得不要和$k1$与$k2$的转移重复计算贡献):
```
if(k1!=0&&k2!=0&&flg2==1)
res+=dfs2(len-1,k1,k2,cnt1,cnt2,num[len]==0&&flg1,flg2);
```
## 代码
注意,这里数位dp采用更简单的记忆化搜索形式。
```
#include<stdio.h>
#include<string.h>
const int maxl=25;
long long i,j,k,m,n,len,ans;
long long num[maxl],f[maxl][maxl][maxl][2][2];
long long dfs1(long long len,long long k,long long cnt1,long long cnt2,long long flg1,long long flg2){
if(len==0)
return cnt1>=cnt2;
if(f[len][cnt1][cnt2][flg1][flg2]!=-1)
return f[len][cnt1][cnt2][flg1][flg2];
long long res=0;
for(long long i=0;i<=9;i++)
if(i<=num[len]||flg1==0)
res+=dfs1(len-1,k,cnt1+(i!=0||flg2==0)*(i==k),cnt2+(i!=0||flg2==0)*(i!=k),i==num[len]&&flg1,i==0&&flg2);
return f[len][cnt1][cnt2][flg1][flg2]=res;
}
long long calc1(long long x,long long k){
memset(f,-1,sizeof(f));
for(len=0;x;x/=10)
num[++len]=x%10;
return dfs1(len,k,0,0,1,1);
}
long long dfs2(long long len,long long k1,long long k2,long long cnt1,long long cnt2,long long flg1,long long flg2){
if(len==0)
return cnt1==cnt2;
if(f[len][cnt1][cnt2][flg1][flg2]!=-1)
return f[len][cnt1][cnt2][flg1][flg2];
long long res=0;
if(k1<=num[len]||flg1==0)
res+=dfs2(len-1,k1,k2,cnt1+(k1!=0||flg2==0),cnt2,k1==num[len]&&flg1,k1==0&&flg2);
if(k2<=num[len]||flg1==0)
res+=dfs2(len-1,k1,k2,cnt1,cnt2+(k2!=0||flg2==0),k2==num[len]&&flg1,k2==0&&flg2);
if(k1!=0&&k2!=0&&flg2==1)
res+=dfs2(len-1,k1,k2,cnt1,cnt2,num[len]==0&&flg1,flg2);
return f[len][cnt1][cnt2][flg1][flg2]=res;
}
long long calc2(long long x,long long k1,long long k2){
memset(f,-1,sizeof(f));
for(len=0;x;x/=10)
num[++len]=x%10;
return dfs2(len,k1,k2,0,0,1,1);
}
int main(){
scanf("%lld%lld",&n,&m);
for(i=0;i<=9;i++)
ans+=calc1(m,i)-calc1(n-1,i);
for(i=0;i<=9;i++)
for(j=i+1;j<=9;j++)
ans-=calc2(m,i,j)-calc2(n-1,i,j);
printf("%lld\n",ans);
return 0;
}
```