P5824 十二重计数法

· · 个人记录

感觉不难,速通了。

I

[\frac{x^n}{n!}](\text{e}^x)^m=m^n

一个盒子的 EGF 是 \text{e}^x,拆分到 m 个盒子即 (\text{e}^x)^m

II

[\frac{x^n}{n!}](1+x)^m=\binom{m}{n}n!

一个盒子的 EGF 是 \frac{x^0}{0!}+\frac{x^1}{1!}

III

[\frac{x^n}{n!}](\text{e}^x-1)^m=[\frac{x^n}{n!}]\sum\limits_{i=0}^m\binom{m}{i}(-1)^{m-i}(\text{e}^x)^i=\sum\limits_{i=0}^m\binom{m}{i}(-1)^{m-i}i^n

一个盒子的 EGF \text{e}^x-1 表示任意放 减去 一个不放。

IV

空盒子需要互相区分,而有球的盒子已经被球区分了,枚举有球的盒子数量。

[\frac{x^n}{n!}]\sum\limits_{i=0}^{m}\frac{1}{i!}(\text{e}^x-1)^i=[\frac{x^n}{n!}]\sum\limits_{i=0}^m\frac{1}{i!}\sum\limits_{j=0}^{i}\binom{i}{j}(-1)^{i-j}(\text{e}^{x})^j =\sum\limits_{i=0}^{m}\frac{1}{i!}\sum\limits_{j=0}^{i}\binom{i}{j}(-1)^{i-j}j^n=\sum\limits_{i=0}^{m}\sum\limits_{j=0}^{i}\frac{1}{(i-j)!j!}(-1)^{i-j}j^n

转为枚举 k=i-j,那么 k=0,1,\dots m-j

=\sum\limits_{j=0}^{m}\frac{j^n}{j!}\sum\limits_{k=0}^{m-j}\frac{(-1)^k}{k!}

现在关于 j,k 独立了,直接预处理后半部分即可。

这就是第二类斯特林数 S_{n,i} 的行和,实际上我们是在容斥有多少个空盒子。

所以其实也可以算一行 S 来做?

V

[\frac{x^n}{n!}]\sum\limits_{i=0}^{m}\frac{1}{i!}x^i=[n\le m]

VI

[\frac{x^n}{n!}]\frac{1}{m!}(\text{e}^x-1)^m=\frac{1}{m!}\sum\limits_{i=0}^{m}\binom{m}{i}(-1)^{m-i}i^n

VII

[x^n](1+x+x^2+\dots )^m=[x^n]\frac{1}{(1-x)^m}=\binom{n+m-1}{m-1}

VIII

[x^n](1+x)^m=\binom{m}{n}

IX

[x^n](x(1+x+x^2+\dots))^m=[x^{n-m}](1+x+x^2+\dots )^m=\binom{n-1}{m-1}

X

[x^n]\prod\limits_{i=1}^{m}\frac{1}{1-x^i}

施 ln - exp trick,即可在 \mathcal O(n\log n) 时间内解决。

XI

同 V。

XII

代码: ```cpp #include<bits/stdc++.h> typedef long long ll; typedef unsigned long long ull; typedef long double ld; #define pii pair<ll,ll> #define rep(i,a,b) for(ll i=(a);i<=(b);++i) #define per(i,a,b) for(ll i=(a);i>=(b);--i) using namespace std; bool Mbe; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } inline void write(ll x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); } const ll N=2e6+9; const ll Mod=998244353,G=3,invG=332748118,inv2=(Mod+1)>>1; ll fac[N],ifac[N],inv[N]; ll pw(ll x,ll p){ ll res=1; while(p){ if(p&1)res=res*x%Mod; x=x*x%Mod; p>>=1; } return res; } void Init(ll n){ fac[0]=1; rep(i,1,n)fac[i]=fac[i-1]*i%Mod; ifac[n]=pw(fac[n],Mod-2); per(i,n-1,0)ifac[i]=ifac[i+1]*(i+1)%Mod; rep(i,1,n)inv[i]=ifac[i]*fac[i-1]%Mod; } ll C(ll x,ll y){ if(x<y||y<0)return 0; return fac[x]*ifac[y]%Mod*ifac[x-y]%Mod; } namespace Poly{ struct poly{ vector<int>a; int size()const{return a.size();} void resize(int n){a.resize(n);} int operator[](int n)const{ if((int)a.size()<=n)return 0; return a[n]; } int &operator[](int n){ if((int)a.size()<=n)a.resize(n+1); return a[n]; } }; int r[N],w[N]; int init(int n){ int p=1,c=0; while(p<=n)p<<=1,c++; r[0]=0; rep(i,1,p-1)r[i]=(r[i>>1]>>1)|((i&1)<<(c-1)); return p; } void NTT(poly&a,int n,int sgn){ rep(i,0,n-1){ if(i<r[i])swap(a[i],a[r[i]]); } for(int mid=1;mid<n;mid<<=1){ int wn=pw(sgn==1?G:invG,(Mod-1)/(mid<<1)),R=(mid<<1); for(int j=0;j<n;j+=R){ int w=1; rep(k,0,mid-1){ int x=a[j+k],y=1ll*a[j+k+mid]*w%Mod; a[j+k]=(x+y)%Mod; a[j+k+mid]=(x-y+Mod)%Mod; w=1ll*w*wn%Mod; } } } if(~sgn)return ; ll inv=pw(n,Mod-2); rep(i,0,n-1)a[i]=1ll*a[i]*inv%Mod; } poly operator+(const poly&a,const poly&b){ poly c;c.resize(max(a.size(),b.size())); rep(i,0,max((ll)a.size()-1,(ll)b.size()-1))c[i]=(a[i]+b[i])%Mod; return c; } poly operator*(const poly&a,const int&b){ poly c; c.resize(a.size()); rep(i,0,(int)a.size()-1)c[i]=1ll*a[i]*b%Mod; return c; } poly operator*(const poly&a,const poly&b){ int p=init(a.size()+b.size()); poly tmp1=a,tmp2=b; tmp1.resize(p),tmp2.resize(p); NTT(tmp1,p,1); NTT(tmp2,p,1); rep(i,0,p-1)tmp1[i]=1ll*tmp1[i]*tmp2[i]%Mod; NTT(tmp1,p,-1); tmp1.resize(a.size()+b.size()); return tmp1; } poly Inv(int n,const poly&a){ poly b; if(n==1){ b.resize(1); b[0]=pw(a[0],Mod-2); return b; } b=Inv((n+1)/2,a); int p=init(n*2); b.resize(p); poly tmp1;tmp1.resize(p); rep(i,0,n-1)tmp1[i]=a[i]; rep(i,n,p-1)tmp1[i]=0; NTT(tmp1,p,1),NTT(b,p,1); rep(i,0,p-1)b[i]=1ll*(2-1ll*tmp1[i]*b[i]%Mod+Mod)*b[i]%Mod; NTT(b,p,-1); b.resize(n); return b; } poly Sqrt(int n,const poly&a){ poly b; if(n==1){ b.resize(1); b[0]=1; return b; } b=Sqrt((n+1)/2,a); int p=init(n*2); b.resize(p); poly tmp1=Inv(n,b); poly tmp2; tmp1.resize(p),tmp2.resize(p); rep(i,0,n-1)tmp2[i]=a[i]; rep(i,n,p-1)tmp2[i]=0; NTT(tmp2,p,1),NTT(b,p,1),NTT(tmp1,p,1); rep(i,0,p-1)b[i]=1ll*(b[i]+1ll*tmp1[i]*tmp2[i])%Mod*inv2%Mod; NTT(b,p,-1); b.resize(n); return b; } poly Derivative(int n,const poly&a){ poly b; b.resize(n); rep(i,1,n-1)b[i-1]=1ll*i*a[i]%Mod; b[n-1]=0; return b; } poly Intergral(int n,const poly&a){ poly b; b.resize(n); rep(i,1,n-1)b[i]=1ll*inv[i]*a[i-1]%Mod; b[0]=0; return b; } poly Ln(int n,const poly&a){ poly c=Derivative(n,a); poly d=Inv(n,a); c=c*d; c.resize(n); c=Intergral(n,c); return c; } poly Exp(int n,const poly&a){ poly b; if(n==1){ b.resize(1); b[0]=1; return b; } b=Exp((n+1)/2,a); b.resize(n); poly tmp1=Ln(n,b); int p=init(n*2); b.resize(p),tmp1.resize(p); rep(i,0,n-1)tmp1[i]=((a[i]-tmp1[i]+(!i))%Mod+Mod)%Mod; rep(i,n,p-1)b[i]=tmp1[i]=0; NTT(tmp1,p,1),NTT(b,p,1); rep(i,0,p-1)b[i]=1ll*b[i]*tmp1[i]%Mod; NTT(b,p,-1); b.resize(n); return b; } poly Pow(int n,const poly&a,int k1,int k2){ //k mod P = k1, k mod phi(P) = k2 poly t=a; ll rsh=0; for(int i=0;i<n&&!t[i];++i)rsh++; poly b; if(rsh*k1>n)return b; int u=pw(t[rsh],Mod-2),v=pw(t[rsh],k2); rep(i,0,n-1)t[i]=1ll*t[i+rsh]*u%Mod; t=Ln(n,t); rep(i,1,n-1)t[i]=1ll*t[i]*k1%Mod; t=Exp(n,t); rsh*=k1; rep(i,rsh,n-1)b[i]=1ll*t[i-rsh]*v%Mod; return b; } } using namespace Poly; ll n,m; namespace Q1{ void solve(){ write(pw(m,n)),putchar('\n'); } } namespace Q2{ void solve(){ write(C(m,n)*fac[n]%Mod),putchar('\n'); } } namespace Q3{ void solve(){ ll ans=0; rep(i,0,m){ ll coef=((m-i)&1?Mod-1:1)*C(m,i)%Mod*pw(i,n)%Mod; ans=(ans+coef)%Mod; } write(ans),putchar('\n'); } } namespace Q4{ ll pre[N]; void solve(){ pre[0]=1; rep(i,1,m)pre[i]=(pre[i-1]+(i&1?Mod-1:1)*ifac[i])%Mod; ll ans=0; rep(i,0,m)ans=(ans+pw(i,n)*ifac[i]%Mod*pre[m-i])%Mod; write(ans),putchar('\n'); } } namespace Q5{ void solve(){ write(n<=m),putchar('\n'); } } namespace Q6{ void solve(){ ll ans=0; rep(i,0,m){ ll coef=((m-i)&1?Mod-1:1)*C(m,i)%Mod*pw(i,n)%Mod*ifac[m]%Mod; ans=(ans+coef)%Mod; } write(ans),putchar('\n'); } } namespace Q7{ void solve(){ write(C(n+m-1,m-1)),putchar('\n'); } } namespace Q8{ void solve(){ write(C(m,n)),putchar('\n'); } } namespace Q9{ void solve(){ write(C(n-1,m-1)),putchar('\n'); } } namespace Q10{ poly f; void solve(){ f.resize(n+1); rep(i,1,m){ rep(j,1,n/i)f[i*j]=(f[i*j]+ifac[j]*fac[j-1])%Mod; } f=Exp(n+1,f); write(f[n]),putchar('\n'); } } namespace Q11{ void solve(){ write(n<=m),putchar('\n'); } } namespace Q12{ void solve(){ if(n>=m)write(Q10::f[n-m]),putchar('\n'); else puts("0"); } } bool Med; int main(){ cerr<<fabs(&Med-&Mbe)/1048576.0<<"MB\n"; n=read(),m=read(); Init(4e5); Q1::solve(); Q2::solve(); Q3::solve(); Q4::solve(); Q5::solve(); Q6::solve(); Q7::solve(); Q8::solve(); Q9::solve(); Q10::solve(); Q11::solve(); Q12::solve(); return 0; } ```