#排列组合#美团2018年CodeM大赛-决赛 A-Exam

题目


分析

因为第一名所在的学校一定会发喜报,
所以只有一个学校发喜报说明其它学校都没有发喜报
钦定第一名所在的学校为1,总方案要乘\(n\),那么两个1之间不可能出现两个相同的学校的学生
那么可以分成两部分,按照乘法原理,左边是在剩下的\(n-1\)个学校中选出\(i\)个进行排列,
右边是在剩下的\(2n-2-i\)个位置进行全排列,由于有\(n-i-1\)个学校需要2个位置,按照多重集的排列数还要除以\(2^{n-i-1}\)
总而言之,

\[ans=n\sum_{i=0}^{n-1}\frac{P_{n-1}^i(2n-2-i)!}{2^{n-i-1}}=n!\times \sum_{i=0}^{n-1}\frac{(2n-2-i)!}{(n-i-1)!2^{n-i-1}} \]


代码

#include <cstdio>
#define rr register
using namespace std;
const int mod=998244353,N=1000011;
int n,fac[N<<1],inv[N],two[N],ans;
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
signed main(){
	scanf("%d",&n),fac[0]=fac[1]=inv[0]=inv[1]=two[0]=1;
	for (rr int i=2;i<=n;++i) inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
	for (rr int i=1;i<=n;++i) two[i]=1ll*two[i-1]*inv[2]%mod; 
	for (rr int i=2;i<=n;++i) inv[i]=1ll*inv[i-1]*inv[i]%mod;
	for (rr int i=2;i<=2*n;++i) fac[i]=1ll*fac[i-1]*i%mod;
	for (rr int i=0;i<n;++i) ans=mo(ans,1ll*fac[n*2-2-i]*two[n-i-1]%mod*inv[n-i-1]%mod);
	return !printf("%d",1ll*ans*fac[n]%mod);
}
posted @ 2020-08-11 14:03  lemondinosaur  阅读(112)  评论(0编辑  收藏  举报