奇妙的题。
你先得会另外一个nlogn的LIS算法。(我一直只会BIT。。。。。)
然后维护下每个数码作为结尾出现过没有就完了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> long long t,l,r,k,ret=0,bit[21]; struct pnt { long long k[11]; }dp[22][1<<10]; void reset() { for (long long i=0;i<=21;i++) for (long long j=0;j<(1<<10);j++) for (long long k=0;k<=10;k++) dp[i][j].k[k]=-1; } void get_bit(long long x) { ret=0; while (x) {bit[++ret]=x%10;x/=10;} } long long bit_cnt(long long x) { long long ret=0; while (x) {if (x&1) ret++;x>>=1;} return ret; } long long get_sets(long long sets,long long x) { if (sets&(1<<x)) return sets; sets|=(1<<x); for (long long i=x+1;i<=9;i++) { if (sets&(1<<i)) { sets^=(1<<i); return sets; } } return sets; } pnt comb(pnt x,pnt y) { for (long long i=1;i<=10;i++) x.k[i]+=y.k[i]; return x; } pnt dfs(long long pos,long long sets,bool flag) { if (!pos) { long long now=bit_cnt(sets);pnt ret; for (long long i=1;i<=10;i++) { if (i==now) ret.k[i]=1; else ret.k[i]=0; } return ret; } if ((!flag) && (~dp[pos][sets].k[1])) return dp[pos][sets]; pnt ans;long long up=flag?bit[pos]:9; for (long long i=1;i<=10;i++) ans.k[i]=0; for (long long i=0;i<=up;i++) ans=comb(ans,dfs(pos-1,get_sets(sets,i),flag&&i==up)); if (!flag) dp[pos][sets]=ans; return ans; } long long ask(long long x) { if (!x) return 0; get_bit(x);long long ans=0; for (long long i=1;i<=ret-1;i++) for (long long j=1;j<=9;j++) ans+=dfs(i-1,1<<j,0).k[k]; for (long long j=1;j<=bit[ret]-1;j++) ans+=dfs(ret-1,1<<j,0).k[k]; ans+=dfs(ret-1,1<<bit[ret],1).k[k]; return ans; } void work(long long x) { scanf("%lld%lld%lld",&l,&r,&k); printf("Case #%lld: %lld ",x,ask(r)-ask(l-1)); } int main() { scanf("%lld",&t);reset(); for (long long i=1;i<=t;i++) work(i); return 0; }