ARC096E题解

\(F[n]\) 表示钦定 \(n\) 个数出现次数不大于 \(1\)

容易得到答案是 \(\sum_{i=0}^{n}\binom{n}{i}(-1)^iF[i]\)

枚举一共被划分成了 \(i\) 个集合,但是因为可能不会被划分到任何一个集合,所以再加入一个元素表示和这个元素属于同一个集合就是没被划分,有:

\[F[n]=2^{2^{N-n}}\sum_{i=0}^{n}\begin{Bmatrix}n+1\\i+1\end{Bmatrix}(2^i)^{N-n} \]

不知道 \(\sum_{i=0}^{n}\begin{Bmatrix}n\\i\end{Bmatrix}x^i\) 能不能做到 \(O(n\log n)\)

#include<cstdio>
const int M=3005;
struct Barrett{
	typedef unsigned long long ull;
	typedef __uint128_t LL;
	ull B,m;
	Barrett(const int&m=2):m(m),B((LL(1)<<64)/m){}
	friend inline ull operator%(const ull&a,const Barrett&mod){
		ull r=a-mod.m*(LL(mod.B)*a>>64);return r>=mod.m?r-mod.m:r;
	}
}mod;
int n,m,S2[M],pw2[M],fac[M],ifac[M];
inline int pow(int a,int b=m-2){
	int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
signed main(){
	int ans(0);scanf("%d%d",&n,&m);mod=Barrett(m);S2[0]=1;pw2[0]=1;for(int i=1;i<=n;++i)pw2[i]=pw2[i-1]*2%(m-1);
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;for(int i=2;i<=n;++i)ifac[i]=1ll*(m-m/i)*ifac[m%i]%mod;
	for(int i=1;i<=n;++i)fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*ifac[i]%mod;
	for(int i=0;i<=n;++i){
		const int&c=pow(2,n-i);int sum(0);
		for(int j=i+1;j>=1;--j)S2[j]=(S2[j-1]+1ll*j*S2[j])%mod;S2[0]=0;
		for(int t(1),j=0;j<=i;++j)sum=(sum+1ll*S2[j+1]*t)%mod,t=1ll*t*c%mod;
		ans=(ans+1ll*ifac[i]*ifac[n-i]%mod*fac[n]%mod*(i&1?m-pow(2,pw2[n-i]):pow(2,pw2[n-i]))%mod*sum)%mod;
	}
	printf("%d",ans);
}
posted @ 2022-08-18 10:41  Prean  阅读(17)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};