1 //HDU - 5787为例
2 //求区间[L,R]内,任意相邻k位(如果位数不足k,就是全部的数位)没有两两相同的数位的数的个数
3 LL l,r;
4 int k;
5 int num[20];
6 LL dp[20][10010][5];
7 //pos表示当前处理的位置(一般从高到低)
8 //limit是限制当前这位能否随便取,即决定top=num[pos]或top=9。
9 //非limit的状态可以记录起来,因为此时pos后面的数字都可以随便取,所以状态是一样的。
10 //pre表示上一位的数字或是上一个状态的数字
11 //dig是表示目前最多几位数字相邻数字互不相同。
12 LL dfs(int pos,int limit,int pre,int dig)
13 {
14
15 LL res=0;
16 if(pos<0)return 1;
17 if(!limit&&dp[pos][pre][dig]!=-1)return dp[pos][pre][dig];
18 int top=limit?num[pos]:9;
//---------------------只需根据题意修改for循环的语句即可------------------------------
19 for(int i=0;i<=top;i++)
20 {
21 int j;
22 int s=pre;
23 for(j=0;j<dig;j++)
24 {
25 if(s%10==i)break;
26 else s/=10;
27 }
28 if(j!=dig)continue;
29 if(i==0&&dig==0)res+=dfs(pos-1,limit&&(i==num[pos]),pre,dig);
30 res+=dfs(pos-1,limit&&(i==num[pos]),(pre%1000)*10+i,min(dig+1,k-1));
31 }
//--------------------------------------------------------------------------------
32 if(!limit)dp[pos][pre][dig]=res;
33 return res;
34 }
35 LL solve(LL n)
36 {
37 int cnt=0;
38 mt(dp,-1);
39 while(n)
40 {
41 num[cnt++]=n%10;
42 n/=10;
43 }
44 return dfs(cnt-1,1,0,0);
45 }
46 int main()
47 {
48 #ifdef Local
49 freopen("data.txt","r",stdin);
50 #endif
51 ios::sync_with_stdio(false);
52 cin.tie(0);
53 while(cin>>l>>r>>k)
54 {
55 cout<<solve(r)-solve(l-1)<<endl;
56 }
57 return 0;
58 #ifdef Local
59 cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
60 #endif
61 }