P5825 排列计数
直接无脑生成函数。
题目要求升高数。
设 \(g_{i,j}\) 表示排列长度 i,升高为 j 的方案数。
考虑最大元素的位置所产生的贡献可以得到。
\[g_{i,j}=
\begin{cases}
1\quad i=0,j=0\\
(i-j)g_{i-1,j-1}+(j+1)g_{i-1,j}\quad 0\le j<i \\
0\quad \text{otherwise}
\end{cases}
\]
设 \(G(x,y)=\sum_{i=0,j=0}g_{i,j}\frac{x^i}{i!}y^j\)。
\[G=\sum_{i=0,j=0}g_{i,j}\frac{x^i}{i!}y^j\\
\frac{\partial G}{\partial x}=\sum_{i=0,j=0}[ (i+1-j)g_{i,j-1}+(j+1)g_{i,j}]\frac{x^i}{i!}y^j\\
\frac{\partial G}{\partial x}=\sum_{i=0,j=0}(i+1-j)g_{i,j-1}\frac{x^i}{i!}y^j
+y\frac{\partial G}{\partial y}+G\\
\frac{\partial G}{\partial x}=\sum_{i=0,j=0}(i-j)g_{i,j}\frac{x^i}{i!}y^{j+1}
+y\frac{\partial G}{\partial y}+G\\
\frac{\partial G}{\partial x}=y(x\frac{\partial G}{\partial x}-y\frac{\partial G}{\partial y})+y\frac{\partial G}{\partial y}+G\\
(1-xy)\frac{\partial G}{\partial x}+(y^2-y)\frac{\partial G}{\partial y}=G\\
\]
这是一个一阶变系数线性齐次偏微分方程不觉得名字很好玩吗。
会的 dalao 可以直接自行进行求解了。
感谢王老师愿意教我。
一阶变系数线性齐次偏微分方程
我会讲的通俗易懂点,想要看严谨的请移步。注意我们设 \(x,y\in(0,1)\)。
我们考虑引入参数 \(t\)(特征线法)。
而 \(G\) 对 \(t\) 的全导数有。
\[\frac{dG}{dt}=\frac{dx}{dt}G_x+\frac{dy}{dt}G_y
\]
发现这个和我们的方程很像,于是可以列出。
\[\begin{cases}
\frac{dx}{dt}=1-xy\\
\frac{dy}{dt}=y^2-y\\
\frac{dG}{dt}=G\\
\end{cases}
\]
然后我们两两消掉。
\[\frac{dy}{dG}=\frac{y(y-1)}{G}\\
(\frac{1}{y-1}-\frac{1}{y})dy=\frac{1}{G}dG\\
\ln|G|=\ln|y-1|-\ln|y|+C\\
\ln G=\ln\frac{1-y}{y}+C\\
G=\frac{1-y}{y}e^C\\
C_1=\frac{Gy}{1-y}\\
\frac{dx}{dy}=\frac{1-xy}{y(y-1)}\\
\frac{dx}{dy}+\frac{x}{y-1}=\frac{1}{y(y-1)}\\
\mu =e^{\int \frac{1}{y-1}dy}=|y-1|=1-y\\
\frac{dx}{dy}(1-y)-x=-\frac{1}{y}\\
\frac{d}{dy}(x(1-y))=-\frac{1}{y}\\
x(1-y)=-\ln y+C\\
C_2=x(1-y)+\ln y\\
\]
求出两个常数,那么它们一定存在某种关系 \(C_1=\phi(C_2)\)。
然后我们把边界值代入求出 \(\phi\)。
\[C_1=\frac{Gy}{1-y}\\
C_2=x(1-y)+\ln y\\
G(0,y)=1\\
\frac{y}{1-y}=\phi(\ln y)\\
s=\ln y\\
\phi(s)=\frac{e^s}{1-e^s}=\frac{1}{e^{-s}-1}\\
\frac{Gy}{1-y}=\frac{1}{e^{-(x(1-y)+\ln y)}-1}\\
G=\frac{1-y}{e^{-x(1-y)}-y}=\frac{(1-y)e^{x(1-y)}}{1-ye^{x(1-y)}}\\
\]
这样我们就求出 \(G\) 了。
然后可以求出 \(g_{i,j}\)。
\[\begin{aligned}
G(x,y)&=\frac{(1-y)e^{x(1-y)}}{1-ye^{x(1-y)}}\\
&=(1-y)e^{x(1-y)}\sum_{i=0}(ye^{x(1-y)})^i\\
&=(1-y)\sum_{j=0}y^j e^{x(1-y)(j+1)}\\
&=(1-y)\sum_{j=0}y^j \sum_{i=0}((1-y)(j+1))^i\frac{x^i}{i!}\\
&=\sum_{i=0}\frac{x^i}{i!}(1-y)^{i+1}\sum_{j=0}y^j(j+1)^i \\
&=\sum_{i=0}\frac{x^i}{i!}\sum_{s=0}^{i+1}(-1)^{s}\binom{i+1}{s}y^s\sum_{j=0}y^j(j+1)^i \\
&=\sum_{i=0}\frac{x^i}{i!}\sum_{j=0}y^j\sum_{s=0}^{j}(-1)^s\binom{i+1}{s}(j-s+1)^i \\
\end{aligned}
\\
g_{n,m}=[\frac{x^n}{n!}y^m]G=\sum_{s=0}^{m}(-1)^s\binom{n+1}{s}(m-s+1)^n
\]
最后直接卷积一下即可,时间复杂度 \(O(N\log N)\)。
code
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,r,l) for(int i=(r);i>=(l);--i)
const int N=(1<<20)+5;
const ll mod=998244353,G=3,IG=332748118;
int n,r[N];
ll fac[N],inv[N];
ll C(int n,int m){return n<m||m<0?0ll:fac[n]*inv[m]%mod*inv[n-m]%mod;}
ll pom(ll a,ll b){ll res=1;for(;b;b>>=1,a=a*a%mod) if(b&1)res=res*a%mod;return res;}
void NTT(ll *a,int op,int lim){
rep(i,0,lim-1)if(i<r[i])swap(a[i],a[r[i]]);
for(int mid=1;mid<lim;mid<<=1){
ll wn=pom(op==1?G:IG,(mod-1)/(mid<<1)),w=1;
for(int j=0;j<lim;j+=(mid<<1),w=1)
for(int k=j;k<j+mid;++k,w=(ll)w*wn%mod){
ll x=a[k],y=a[k+mid]*w%mod;
a[k]=(x+y)%mod,a[k+mid]=(x-y+mod)%mod;
}
}
if(op==-1){
ll in=pom(lim,mod-2);
rep(i,0,lim-1)a[i]=a[i]*in%mod;
}
}
void conv(ll *a,ll *b,int n,int m){
int lim=1,_=0;
while(lim<=n+m)lim<<=1,_++;
rep(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<_-1);
fill(a+n+1,a+lim,0);fill(b+m+1,b+lim,0);
NTT(a,1,lim);NTT(b,1,lim);
rep(i,0,lim-1)a[i]=a[i]*b[i]%mod;
NTT(a,-1,lim);
}
ll a[N],b[N];
void solve(){
cin>>n;
rep(i,0,n+1)a[i]=(i&1)?mod-C(n+1,i):C(n+1,i);
rep(i,0,n+1)b[i]=pom(i,n);
conv(a,b,n+1,n+1);
rep(i,1,n+1)cout<<a[i]<<" ";
}
int main(){
cin.tie(0)->ios::sync_with_stdio(false);
fac[0]=1;
rep(i,1,N-1) fac[i]=fac[i-1]*i%mod;
inv[N-1]=pom(fac[N-1],mod-2);
per(i,N-2,0) inv[i]=inv[i+1]*(i+1)%mod;
solve();
}

浙公网安备 33010602011771号