Solution:P5824(十二重计数法)

5 篇文章 0 订阅
2 篇文章 0 订阅

题目链接

Link:P5824

解题思路

An   interesting   problem. \textsf{An interesting problem.} An interesting problem.
我们把问题的要求这样分开:
满足球有标号的标上 A A A,满足盒子有标号的标上 B B B,满足至多放一个球的标 C 1 C_1 C1,满足至少放一个球的标 C 2 C_2 C2 p = 998244353 p=998244353 p=998244353 为模数。

Type 1 : A B 1:AB 1:AB

I : A B \mathrm{I}:AB I:AB

Rating:2   stars(Easy). \color{skyblue}\textsf{Rating:2 stars(Easy).} Rating:2 stars(Easy).
每个球都有 m m m 个盒子可选,一共 n n n 个球。
显然答案为 m n m^n mn
时间复杂度 O ( log ⁡ n ) ( ≈ O ( 1 ) ) \Omicron(\log n)(\approx\Omicron(1)) O(logn)(O(1))

I  ⁣ I : A B C 1 \mathrm{I\!I}:ABC_1 II:ABC1

Rating:2   stars(Easy). \color{skyblue}\textsf{Rating:2 stars(Easy).} Rating:2 stars(Easy).
n > m n>m n>m 时,盒子装不下球,显然答案为 0 0 0
否则答案显然为 A m n A_m^n Amn
时间复杂度 O ( log ⁡ p ) ( ≈ O ( 1 ) ) \Omicron(\log p)(\approx\Omicron(1)) O(logp)(O(1))

I  ⁣ I  ⁣ I : A B C 2 \mathrm{I\!I\!I}:ABC_2 III:ABC2

Rating:4   stars(Normal). \color{ForestGreen}\textsf{Rating:4 stars(Normal).} Rating:4 stars(Normal).
n < m n<m n<m 时显然答案为 0 0 0
否则,第二类Stirling数的意义就是把不同的球放到同样的盒子里。现在盒子不一样,全排列不就行了?
答案为 m ! { n m } m!\begin{Bmatrix}n\\m\end{Bmatrix} m!{nm}。(其实 V  ⁣ I \mathrm{V\!I} VI 就是先计算这玩意再乘上 1 m ! \dfrac 1 {m!} m!1
时间复杂度 O ( m log ⁡ n m p ) ( ≈ O ( m ) ) \Omicron(m\log nmp)(\approx\Omicron(m)) O(mlognmp)(O(m))

Type 2 : A 2:A 2:A

I  ⁣ V : A \mathrm{I\!V}:A IV:A

Rating:6   stars(Hard). \color{ffd000}\textsf{Rating:6 stars(Hard).} Rating:6 stars(Hard).
看起来这玩意很像第二类Stirling数( V  ⁣ I \mathrm{V\!I} VI)。但是,又不是。少了一个集合非空的条件。
那么,我们能不能把它的公式改一改呢?我没试过。不过,我们可以用另外一种方法。
枚举有几个盒子有球。我们得到
∑ i = 1 min ⁡ ( m , n ) { n i } \sum_{i=1}^{\min(m,n)}\begin{Bmatrix}n\\i\end{Bmatrix} i=1min(m,n){ni}
好的,第二类Stirling数(行)的板子即可。
时间复杂度 O ( n log ⁡ n p ) ( ≈ O ( n log ⁡ n ) ) \Omicron(n\log np)(\approx\Omicron(n\log n)) O(nlognp)(O(nlogn))

V : A C 1 \mathrm{V}:AC_1 V:AC1

Easiest   Subtask. \color{skyblue}\textsf{Easiest Subtask.} Easiest Subtask.
Rating:1   star(Easy). \color{skyblue}\textsf{Rating:1 star(Easy).} Rating:1 star(Easy).
显然装得下是 1 1 1,装不下是 0 0 0
时间复杂度 O ( 1 ) \Omicron(1) O(1)

V  ⁣ I : A C 2 \mathrm{V\!I}:AC_2 VI:AC2

Rating:3   stars(Normal). \color{ForestGreen}\textsf{Rating:3 stars(Normal).} Rating:3 stars(Normal).
n < m n<m n<m 时显然答案为 0 0 0
否则答案显然为 { n m } \begin{Bmatrix}n\\m\end{Bmatrix} {nm}
时间复杂度 O ( m log ⁡ n m p ) ( ≈ O ( m ) ) \Omicron(m\log nmp)(\approx\Omicron(m)) O(mlognmp)(O(m))

Type 3 : B 3:B 3:B

V  ⁣ I  ⁣ I : B \mathrm{V\!I\!I}:B VII:B

Rating:4   stars(Normal). \color{ForestGreen}\textsf{Rating:4 stars(Normal).} Rating:4 stars(Normal).
我们考虑先让每个盒子放一个球(即设球数为 n + m n+m n+m),即转化成 I  ⁣ X \mathrm{I\!X} IX
时间复杂度 O ( log ⁡ p ) ( ≈ O ( 1 ) ) \Omicron(\log p)(\approx\Omicron(1)) O(logp)(O(1))

V  ⁣ I  ⁣ I  ⁣ I : B C 1 \mathrm{V\!I\!I\!I}:BC_1 VIII:BC1

Rating:2   stars(Easy). \color{skyblue}\textsf{Rating:2 stars(Easy).} Rating:2 stars(Easy).
n > m n>m n>m 时,盒子装不下球,显然答案为 0 0 0
否则答案显然为 C m n C_m^n Cmn
时间复杂度 O ( log ⁡ p ) ( ≈ O ( 1 ) ) \Omicron(\log p)(\approx\Omicron(1)) O(logp)(O(1))

I  ⁣ X : B C 2 \mathrm{I\!X}:BC_2 IX:BC2

Rating:3   stars(Normal). \color{ForestGreen}\textsf{Rating:3 stars(Normal).} Rating:3 stars(Normal).
用插板法可得答案为 C n − 1 m − 1 C_{n-1}^{m-1} Cn1m1
时间复杂度 O ( log ⁡ p ) ( ≈ O ( 1 ) ) \Omicron(\log p)(\approx\Omicron(1)) O(logp)(O(1))

Type 4 : ∅ 4:\emptyset 4:

X : ∅ \mathrm{X}:\emptyset X:

Rating:8   stars(Harder). \color{ff5500}\textsf{Rating:8 stars(Harder).} Rating:8 stars(Harder).
我们要求的答案是把 n n n 划分为 m m m 个自然数的方案数。设它为 p n , m p_{n,m} pn,m,有 p n , m = p n − m , m + p n , m − 1 p_{n,m}=p_{n-m,m}+p_{n,m-1} pn,m=pnm,m+pn,m1。考虑优化,设多项式
F i ( x ) = ∑ j = 0 ∞ p j , i x j F_i(x)=\sum_{j=0}^\infty p_{j,i}x^j Fi(x)=j=0pj,ixj
则有
F i ( x ) = F i − 1 ( x ) ∑ j = 0 ∞ x j i = F i − 1 ( x ) 1 − x i = ∏ j = 1 i 1 1 − x j F_i(x)=F_{i-1}(x)\sum_{j=0}^\infty x^{ji}=\frac{F_{i-1}(x)}{1-x^i}=\prod_{j=1}^i\frac 1{1-x^j} Fi(x)=Fi1(x)j=0xji=1xiFi1(x)=j=1i1xj1
参考付公主的背包(P4389) ln ⁡ + exp ⁡ \ln+\exp ln+exp 法,可得
∏ j = 1 i 1 1 − x j = exp ⁡ ∑ j = 1 i ( − ln ⁡ ( 1 − x j ) ) = exp ⁡ ∑ j = 1 i ∑ k = 1 ∞ x j k k \prod_{j=1}^i\frac 1{1-x^j}=\exp\sum_{j=1}^i(-\ln(1-x^j))=\exp\sum_{j=1}^i\sum_{k=1}^\infty \frac {x^{jk}} k j=1i1xj1=expj=1i(ln(1xj))=expj=1ik=1kxjk
我们要求的即为
[ x n ] F m = [ x n ] exp ⁡ ∑ i = 1 m ∑ j = 1 ∞ x i j j [x^n]F_m=[x^n]\exp\sum_{i=1}^m\sum_{j=1}^\infty \frac {x^{ij}} j [xn]Fm=[xn]expi=1mj=1jxij

X  ⁣ I : C 1 \mathrm{X\!I}:C_1 XI:C1

Easiest   Subtask. \color{skyblue}\textsf{Easiest Subtask.} Easiest Subtask.
Rating:1   star(Easy). \color{skyblue}\textsf{Rating:1 star(Easy).} Rating:1 star(Easy).
显然装得下是 1 1 1,装不下是 0 0 0
时间复杂度 O ( 1 ) \Omicron(1) O(1)

X  ⁣ I  ⁣ I : C 2 \mathrm{X\!I\!I}:C_2 XII:C2

Rating:9   stars(Insane). \color{dd55dd}\textsf{Rating:9 stars(Insane).} Rating:9 stars(Insane).
我们先放 m − n m-n mn 个球进盒子里,便可转化为 X \mathrm{X} X
时间复杂度为 O ( n log ⁡ n ) \Omicron(n\log n) O(nlogn)(可使用 X \mathrm{X} X 的结果直接回答,真实复杂度为 O ( 1 ) \Omicron(1) O(1))。

代码实现

//
#ifndef Polynomial_Class
//这里是长为13KB的多项式全家桶,由于篇幅原因省略
#endif

using namespace std;
using namespace Polynomial;

array<long long,400001> facts,inverses;
polynomial<524288> poly_n_4,poly_m_4,poly_4,poly_exp,poly_ans;

int main(int argc,char* argv[],char* envp[])
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	facts[0]=1;
	for(int i=1;i<=400000;i++)
		facts[i]=facts[i-1]*i%prime;
	long long cntbox,cntball;
	cin>>cntball>>cntbox;
	cout<<fast_pow(cntbox,cntball,prime)<<'\n'<<(cntball>cntbox?0:facts[cntbox]*inverse(facts[cntbox-cntball],prime)%prime)<<'\n';
	long long ans_3=0;
	if(cntball<cntbox)
	{
		cout<<0<<'\n';
		goto endcase_3;
	}
	for(int i=0;i<=cntbox;i++)
		ans_3=(ans_3+fast_pow(prime-1,i,prime)*facts[cntbox]%prime*inverse(facts[i]*facts[cntbox-i]%prime,prime)%prime*fast_pow(cntbox-i,cntball,prime)%prime)%prime;
	cout<<ans_3<<'\n';
	endcase_3:;
	long long ans_4=0;
	for(int i=0;i<=cntball;i++)
		poly_n_4[i]=fast_pow(i,cntball,prime)*inverse(facts[i],prime)%prime,poly_m_4[i]=fast_pow(prime-1,i,prime)*inverse(facts[i],prime)%prime;
	mult(cntball+1,cntball+1,poly_n_4,poly_m_4,poly_4);
	for(int i=1;i<=min(cntball,cntbox);i++)
		ans_4=(ans_4+poly_4[i])%prime;
	cout<<ans_4<<'\n'<<(cntball<=cntbox)<<'\n'<<ans_3*inverse(facts[cntbox],prime)%prime<<'\n'
		<<facts[cntball+cntbox-1]%prime*inverse(facts[cntbox-1]*facts[cntball]%prime,prime)%prime<<'\n'
		<<(cntbox<cntball?0:facts[cntbox]%prime*inverse(facts[cntball]*facts[cntbox-cntball]%prime,prime)%prime)<<'\n'
		<<(cntbox>cntball?0:facts[cntball-1]%prime*inverse(facts[cntbox-1]*facts[cntball-cntbox]%prime,prime)%prime)<<'\n';
	for(int i=1;i<=cntball;i++)
		inverses[i]=inverse(i,prime);
	for(int i=1;i<=min(cntbox,cntball);i++)
		for(int j=1;j*i<=cntball;j++)
			poly_exp[i*j]=(poly_exp[i*j]+inverses[j])%prime;
	exp(cntball+1,poly_exp,poly_ans);
	cout<<poly_ans[cntball]<<'\n'<<(cntball<=cntbox)<<'\n'<<(cntball<cntbox?0:poly_ans[cntball-cntbox]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值