不错的题啊 然而我太菜了orz
想一想 不难发现其实从小到大搜索哪几个数并不会超时
然后就算一下就好了。。。
至于怎么算
就枚举哪个位开始低于n的对应位 剩下的位随便填就用组合数算
如果位数比n少直接算就好了 首位不为0即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline int read(){
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
int n,k,m,a[11],al,ans,c[11],tot,jc[11];
LL d[11];
bool check(){
if(!tot || !c[tot])return 0;
LL s=0; int u=c[(tot+1)>>1];
for(int i=1;i<=tot;++i)
{
int g=c[i]-u; LL o= g>=0?d[g]:d[-g];
if(g<0) s+= k&1?-o:o;
else s+=o;
}
if(s>m)return 0;
return 1;
}
int num[11];
void add(int x){
LL s=jc[x];
for(int i=0;i<=9;++i)s/=jc[num[i]];
ans+=s;
}
void cal(){
for(int i=0;i<=9;++i) num[i]=0;
for(int i=1;i<=tot;++i) num[c[i]]++;
if(tot<al){
for(int j=9;j>0;--j)
if(num[j]>0){
num[j]--;
add(tot-1);
num[j]++;
}
return;
}
for(int i=tot;i>=1;--i){
int o= i==tot?0:-1;
for(int j=a[i]-1;j>o;--j)
if(num[j]>0){
num[j]--;
add(i-1);
num[j]++;
}
if(!num[a[i]])break;
num[a[i]]--; if(i==1)ans++;
}
}
void dfs(int x){
if(check())cal();
if(tot==al)return;
++tot;
for(int i=x;i<=9;++i)
c[tot]=i,dfs(i);
--tot;
}
int main()
{
n=read(),k=read(),m=read();
while(n) a[++al]=n%10,n/=10;
jc[0]=1; for(int i=1;i<=al;++i)jc[i]=jc[i-1]*i;
for(int i=0;i<=9;++i){
d[i]=1;
for(int j=1;j<=k;++j)d[i]*=i;
}
dfs(0);
printf("%d\n",ans);
return 0;
}