奇妙的题。
你先得会另外一个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\n",x,ask(r)-ask(l-1));
}
int main()
{
scanf("%lld",&t);reset();
for (long long i=1;i<=t;i++) work(i);
return 0;
}
来源:http://www.cnblogs.com/ziliuziliu/p/6219612.html