题目链接:点击打开链接
给出小明在迷糊的时候看到的车牌号数字,和真实数字相比:
①真实出现的数字,小明都看到了
②小明只可能把同一个数字看多,不可能看少
③车牌号没有前导零
问真实的数字有可能有多少种情况
先把每个数字出现的次数记录下来,这就是在搜索时每个数字取到的上限
从0到9遍历(相当于10层循环,在这里用递归的方式实现,每层循环的遍历次数即为该层数字出现的次数,代表取多少个这个数)
在最后一层统计用当前这些数字能组成合法数字的个数 ans=总共数字总和的阶乘/(∏每个数字出现次数的阶乘)
#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define sqr(a) (a)*(a)
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,n,m) for(int i=n;i>=m;i--)
#define lan(a,b) memset(a,b,sizeof(a))
#define maxn 100010
using namespace std;
LL num[10];
LL fact[20];
LL nownum[10];
LL ans;
void init()
{
lan(num,0);
lan(fact,0);
lan(nownum,0);
fact[0]=1;
for(int i=1;i<=19;i++)
fact[i]=i*fact[i-1];
}
LL cal()
{
LL tem=0;
for(int i=0;i<=9;i++)
tem+=nownum[i];
//printf("%lld\n",tem);
tem=fact[tem];
//printf("%lld\n",tem);
for(int i=0;i<=9;i++)
{
tem/=fact[nownum[i]];
}
//printf("%lld\n",tem);
return tem;
}
void pou(int x)
{
// printf("x=%d\n",x);
if(x>9)
{
ans+=cal();
//printf("ans=%lld\n",ans);
if(nownum[0]>=1)
{
nownum[0]--;
ans-=cal();
nownum[0]++;
// printf("ans=%lld\n",ans);
}
return;
}
if(num[x])
{
for(int i=1;i<=num[x];i++)
nownum[x]=i,pou(x+1);
}
else
pou(x+1);
}
int main()
{
LL n;
while(~scanf("%lld",&n))
{
init();
ans=0;
while(n)
{
num[n%10]++;
n/=10;
}
pou(0);
printf("%lld\n",ans);
}
return 0;
}