題目連接: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));
}
}