数位DP。dp[i][j][state] 表示最高位为i,数字为j,i位之后k-1个为state的方案数。例如1 2 3 4四个数字,state用1234表示。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\in.txt","r",stdin); freopen("D:\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } LL L,R,dp[21][12][10010]; int k; int f[21],q[10],sz; bool check(int limit,int x) { int tmp=x,tmpsz=0; if(tmp==0) tmpsz=1; while(tmp) tmpsz++, tmp=tmp/10; if(tmpsz>limit) return 0; if(tmpsz<limit-1) return 0; sz=0; if(x==0) f[sz++]=0; while(x) f[sz++]=x%10, x=x/10; if(tmpsz==limit-1) f[sz++]=0; for(int i=0;i<sz;i++) for(int j=i+1;j<=min(sz-1,i+k-1);j++) if(f[i]==f[j]) return 0; return 1; } bool Check(int x) { for(int i=0;i<sz;i++) if(x==f[i]) return 0; return 1; } bool Ch(int x) { for(int i=0;i<sz-1;i++) if(x==f[i]) return 0; return 1; } void init() { memset(dp,0,sizeof dp); for(int i=0;i<=9;i++) dp[1][i][0]=1; for(int i=2;i<=k;i++) { for(int j=0;j<=9;j++) { for(int s=0;s<=9999;s++) { if(!check(i-1,s)) continue; if(!Check(j)) continue; dp[i][j][s]=dp[i][j][s]+dp[i-1][f[sz-1]][s-f[sz-1]*q[sz-1]]; } } } for(int i=k+1;i<=19;i++) { for(int j=0;j<=9;j++) { for(int s=0;s<=9999;s++) { if(!check(k-1,s)) continue; if(!Check(j)) continue; for(int u=0;u<=9;u++) { if(!Ch(u)) continue; int p=s-f[sz-1]*q[sz-1]; dp[i][j][s]+=dp[i-1][f[sz-1]][p*10+u]; } } } } } LL get(LL x) { LL res=0; int g[21]; int len=0; while(x) g[len++]=x%10,x=x/10; for(int i=len;i>=1;i--) g[i]=g[i-1]; for(int i=1;i<=len-1;i++) for(int j=1;j<=9;j++) for(int s=0;s<=9999;s++) res=res+dp[i][j][s]; for(int i=len;i>=1;i--) { int D; if(i==len) D=1; else D=0; for(int j=D;j<g[i];j++) { bool ff=0; for(int s=i+1;s<=min(len,i+k-1);s++) if(g[s]==j) ff=1; if(ff) continue; for(int s=0;s<=9999;s++) { if(dp[i][j][s]==0) continue; bool fail=0; int m=i-1; m=min(k-1,m); check(m,s); for(int pos=sz-1;pos>=0;pos--) for(int pre=i+1;pre<=min(len,i+pos-sz+k-1);pre++) if(f[pos]==g[pre]) fail=1; if(fail) continue; res=res+dp[i][j][s]; } } for(int s=i+1;s<=min(len,i+k-1);s++) if(g[s]==g[i]) return res; } return res; } int main() { q[0]=1; for(int i=1;i<=5;i++) q[i]=10*q[i-1]; while(~scanf("%lld%lld%d",&L,&R,&k)) { init(); printf("%lld ",get(R+1)-get(L)); } return 0; }