版权声明:本文为博主原创文章,转载请注明出处~~ https://blog.csdn.net/hxc2101/article/details/81984666
题目:http://codeforces.com/contest/991/problem/E
题意:有一串数,每个数都出现cnt[i]次 (为解释题意方便,这部分是需要自己计算一下的),对他进行排列组合,要求原数列中的每个数都需要出现>=1次,但不能超过cnt[i]次,且0不能放在开头,(在符合前面要求的前提下新数列长度是任意的),问这样的组合数。
思路:
1.计算每个数字的cnt[i] ;
2.dfs 并用 use[i] 记录每次新数列中该数出现的次数(排列组合的公式中要用到) (use[1] 从1到cnt[i]遍历) ;
3.对于数组中含重复元素的排列组合的种数的计算公式: (解释:分子表示总共有n个数进行全排列;分母中每一小部分表示每个数自己重复的次数进行全排列);
4.减去以0为开头的种数 (解释:分子表示 第一个数放0,那么后面只有n-1个数能放了,对这n-1个数全排列;分母中不同的是 因为开头放了0 所以此时使用0的个数use[0]就是a[0]-1,其他的思路都和上式是相同的)
合起来就是:
//阶乘的值 需要预处理 //注意数据开 long long
#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popans,abm,mmx,avx,tune=native")
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define mkp(a,b) make_pair(a,b)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define fi first
#define se second
#define lc (d<<1) //d*2
#define rc (d<<1|1) //d*2+1
#define eps 1e-9
#define dbg(x) cerr << #x << " = " << x << "\n";
#define mst(a,val) memset(a,val,sizeof(a))
#define stn(a) setprecision(a)//小数总有效位数
#define stfl setiosflags(ios::fixed)//点后位数:cout<<stfl<<stn(a);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI=3.1415926535897932;
const int MAXN=1e5+10;
const ll mod=1e9+7;
ll inline mpow(ll a,ll b){ll ans=1;a%=mod;while(b){if(b&1)ans=(ans*a)%mod;a=(a*a)%mod,b>>=1;}return ans;}
int inline sgn(double x){return (x>-eps)-(x<eps);} //a<b:sgn(a-b)<0
priority_queue<int,vector<int>,greater<int> > qu; //up
priority_queue<int,vector<int>,less<int> > qd; //dn
const int inf = 0x3f3f3f3f; //9
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
char s[50];
ll cnt[20];
ll use[20];
ll jc[20]; //阶乘的值 需要预处理
ll ans=0; //注意数据开 long long
void dfs(ll x)
{
if(x==10)
{
ll sum=0;
for(ll i=0;i<=9;i++) sum+=use[i];
ll tmp=1;
for(ll i=0;i<=9;i++) tmp*=jc[use[i]];
ans+=(jc[sum]/tmp);
if(use[0]>=1) ans=ans-jc[sum-1]/(tmp/jc[use[0]]*jc[use[0]-1]);
return;
}
for(ll i=1;i<=cnt[x];i++) {use[x]=i;dfs(x+1);}
if(cnt[x]==0) {use[x]=0;dfs(x+1);}
}
int main()
{
fio;
cin>>s;
ll len=strlen(s);
for(ll i=0;i<len;i++)
cnt[s[i]-'0']++;
jc[0]=1;
for(ll i=1;i<=19;i++)
jc[i]=jc[i-1]*i;
dfs(0);
cout<<ans<<endl;
}