题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5787
【题意】给定三个数i,j,k。问i-j之间有多少任意k位数都不相同的数。
【分析】数位dp,用dp[pos][p1][p2][p3][p4]表示当前位为第pos位,前第一位为p4,前第二位为p3,前第三位为p2,前第四位为p1的数的满足条件的数的个数。用特殊的10表示前导0。用dfs进行记忆化搜索。搜索过程中用flg标记前位是否取满以确定当前位的取值上限。
【代码】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
LL dp[20][12][12][12][12];
int dig[20];
LL l,r;
int k;
bool check(int p1,int p2,int p3,int p4,int p5){
if(k==2)
return p5!=p4;
if(k==3)
return (p5!=p4 && p5!=p3);
if(k==4)
return (p5!=p4 && p5!=p3 && p5!=p2);
return (p5!=p4 && p5!=p3 && p5!=p2 && p5!=p1);
}
LL dfs(int pos,int p1,int p2,int p3,int p4,bool flg){
if(pos==0)
return p4!=10;
if(!flg && dp[pos][p1][p2][p3][p4]!=-1)
return dp[pos][p1][p2][p3][p4];
int ed=flg?dig[pos]:9;
LL ans=0;
for(int i=0;i<=ed;++i){
if(i==0 && p4==10)
ans+=dfs(pos-1,10,10,10,10,flg && i==ed);
else
if(check(p1,p2,p3,p4,i))
ans+=dfs(pos-1,p2,p3,p4,i,flg && i==ed);
}
if(!flg)
dp[pos][p1][p2][p3][p4]=ans;
return ans;
}
LL cal(LL x){
if(x<=0)
return 0;
LL tmp=x;
int len=0;
while(tmp){
dig[++len]=tmp%10;
tmp/=10;
}
return dfs(len,10,10,10,10,1);
}
int main(){
while(~scanf("%I64d %I64d %d",&l,&r,&k)){
memset(dp,-1,sizeof(dp));
printf("%I64d\n",cal(r)-cal(l-1));
}
}