P2518
题目描述
题解
用has维护先前每个数的个数,然后直接套板子即可
代码
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define int long long
#define ull unsigned long long
#define M 100009
using namespace std;
tr1::unordered_map<ull,int>mp;
const int h=31;
int a[51],num[11],dp[51][M],cnt[11],tot,n;
char s[54];
ull gethas(){
ull has=0;
for(int i=1;i<=9;i++) has=has*h+cnt[i];
return has;
}
int dfs(int pos,int pre,bool limit,int sum){
if(n-pos+1<sum) return 0;
if(pos==n+1&&sum==0) return 1;
if(!limit&&dp[pos][pre]) return dp[pos][pre];
int up=limit?a[pos]:9,ans=0;
for(int i=0;i<=up;i++){
if(i!=0){
if(cnt[i]==num[i]) continue;
cnt[i]++;ull has1=gethas();
if(mp.find(has1)==mp.end()) mp[has1]=++tot;
int x=mp[has1];
ans+=dfs(pos+1,x,limit&&(i==a[pos]),sum-1);
cnt[i]--;
}else ans+=dfs(pos+1,pre,limit&&(i==a[pos]),sum);
}if(!limit) dp[pos][pre]=ans;
return ans;
}
signed main(){
scanf("%s",s+1);
n=strlen(s+1);int sum=0;
for(int i=1;i<=n;i++) a[i]=s[i]-'0',num[a[i]]++;
for(int i=1;i<=9;i++) sum+=num[i];
printf("%lld\n",dfs(1,0,1,sum)-1);
return 0;
}