luogu2518 [HAOI2010] 计数

Posted headboy2002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu2518 [HAOI2010] 计数相关的知识,希望对你有一定的参考价值。

题目大意

 给出一个数字$n$,求满足下列条件的数$x$的个数:

  1. $x<n$
  2. 对于来自于$x$十进制各个数位上的非零数字,它们的种类与个数都与$n$的相同。

思路

入手点

  设$n$有$t$位数字,如果满足上述条件的$x$的位数$t‘$比$t$小,那相当于$x$前面含有$t-t‘$个前缀0!因此如果我们不考虑第1条,那么$x$就是由$n$各个位上数字包括0组成的全排列。

考虑第一条

  我们定义$a_i$为数$n$在第$i$位上的数字,$b_i$则是$x$的。$f(m)$为当$n$与$x$在$m$以上的位数都相等的情况下,满足题目条件的排列个数。若$a_m=b_m$,则转化为子问题$f(m-1)$;如果$b_m<a_m$,则$x$位数比$m$小的那部分无论如何排列,都会满足第一条,故结果为:对于每一个$b_m\in[0,a_m)$,将其锁定在第$m$位,$n$在$m$及以下的位数的所有数字排除掉被安在第一位的$b_m$后,在$m-1$个数中的全排列。由加法原理,这些结果都要相加

怎么求含可重元素的全排列

  已知一个数组,$h_i$表示一个元素的个数,在长度$m$的区间里求它的全排列。其相当于先在区间中安0,共有$C_m^{h_0}$种选法;然后再在剩余的空间$m-h_0$中看看1的安放方式,即$C_{m-h_0}^{h_1}$。以此类推。根据乘法原理,这些组合数要相乘才为结果

注意事项

  • ans用long long!
  • 求组合数递归时不要忘了给C数组赋值!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <cstdlib>
#include <iostream>
using namespace std;

#define ll long long
const int MAX_DIGIT = 55, MAX_NUM = 10;
ll A[MAX_DIGIT];
int NumCnt[MAX_NUM];
ll C[MAX_DIGIT][MAX_DIGIT];

ll Comb(int n, int m)
{
	if (n < 0 || m < 0)
		return 0;
	if (C[n][m])
		return C[n][m];
	else if (m == 0 || m == n)
		return C[n][m] = 1;
	else if (m == 1)
		return C[n][m] = n;
	else if (m > n)
		return 0;
	else
		return C[n][m] = Comb(n - 1, m - 1) + Comb(n - 1, m);
}

ll GetAns(const int len)
{
	if (len == 1)
		return 0;
	ll ans = 0;
	for (int firstNum = 0; firstNum < A[len]; firstNum++)
	{
		NumCnt[firstNum]--;
		int subLen = len - 1;
		ll combAns = 1;
		for (int num = 0; num < 10; num++)
		{
			combAns *= Comb(subLen, NumCnt[num]);
			subLen -= NumCnt[num];
		}
		NumCnt[firstNum]++;
		ans += combAns;
	}
	NumCnt[A[len]]--;
	ans += GetAns(len - 1);
	return ans;
}

int main()
{
	stack<int> st;
	char c;
	while (cin >> c && isdigit(c))
		st.push(c - ‘0‘);
	int len = 0;
	while (!st.empty())
	{
		A[++len] = st.top();
		NumCnt[A[len]]++;
		st.pop();
	}
	cout << GetAns(len) << endl;
	return 0;
}

  

以上是关于luogu2518 [HAOI2010] 计数的主要内容,如果未能解决你的问题,请参考以下文章

P2518 [HAOI2010]计数

P2518 [HAOI2010]计数

P2518 [HAOI2010]计数

[luogu2513 HAOI2009] 逆序对数列 (计数dp)

[HAOI 2010] 计数

bzoj 2425 [HAOI2010]计数 数学