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);
}