質問の意味:
デジタルの文字列は、数字列構成数字列B、満たす解体する必要が:
(B 3 6 Aが存在すると仮定したら、少なくとも現れオーバー1.A番号は、次にBが有し得る1-3 6ヶ月)。
0をリードせずに2.Bは
どのように多くの異なるBの合計を頼みます
例えば、2028 =指定された文字列A
、次にB溶液は:208、280、802、820、2028、2082、2208、2280、2802、2820、8022、8202、8220、の13種類の合計
アイデア:
先计算出数字串A中每种数字各有多少个。
dfs枚举每种数字使用的个数。
假设当前数字总数为k,那么全排列方案数为ans=k!
因为相同的数字交换位置是同一种,所以要去重:
ans=ans/(a[0]!*a[1]!*a[2]!*a[3]!*a[4]!...*a[9]!),其中a[i]是数字i出现的次数
另外有0的时候还要减掉前导零的情况:
挑出一个0作为前导零,然后计算剩下的数的方案数(步骤和上面一样),减掉即可
コード:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=25;
char s[maxm];
int fac[maxm];
int cnt[maxm];
int a[maxm];
int ans;
void dfs(int x){
if(x==10){//如果搜到底了
int tot=0;//总数字个数
for(int i=0;i<10;i++){
tot+=a[i];
}
int now=fac[tot];//全排列方案数
for(int i=0;i<10;i++){
now/=fac[a[i]];//去重
}
if(a[0]>=1){//还要排除前导0的情况
int p=fac[tot-1];//挑出一个0放在开头
p/=fac[a[0]-1];
for(int i=1;i<10;i++){//计算剩下的数的方案数
p/=fac[a[i]];
}
now-=p;//减去
}
ans+=now;
return ;
}
for(int i=1;i<=cnt[x];i++){//枚举选取的数字个数
a[x]=i;
dfs(x+1);
}
if(cnt[x]==0)dfs(x+1);
}
signed main(){
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++){//计算数字个数
cnt[s[i]-'0']++;
}
fac[0]=1;
for(int i=1;i<=n;i++){//预处理阶乘
fac[i]=fac[i-1]*i;
}
dfs(0);
cout<<ans<<endl;
return 0;
}