题解:P7781 「MCOI-Zero / AC6-M07」Selumna Peak

· · 题解

200 紫 AC。

先考虑求出 ans_n

考虑每一对 i<j(a_i,a_j) 的贡献,有 6 种情况:

下面每一行依次对应前面的描述。

\begin{aligned} ans_n= &\sum_{i=1}^n \sum_{j=i+1}^n \sum_{k=2}^n {n-2\choose k-2} \frac{k!}2 \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \sum_{k=0}^{n-2} {n-2\choose k} k! \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \sum_{k=1}^{n-1} \sum_{l=1}^{k} {j-2\choose l-1} {n-j\choose k-l} \ l\ (k-1)! \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \sum_{k=1}^{n-1} \sum_{l=1}^{k} {i-1\choose k-l} {n-i-1\choose l-1} \ l\ (k-1)! \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i<a_j] \sum_{k=2}^{n-1} \sum_{l=1}^{k-1} {j-2\choose k-l-1} {n-j\choose l} \ l\ (k-1)! \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i<a_j] \sum_{k=2}^{n-1} \sum_{l=1}^{k-1} {i-1\choose l} {n-i-1\choose k-l-1} \ l\ (k-1)! \end{aligned}

考虑化简。

对于第一行,我们发现 i,j 并没有用,直接化为 n(n-1)/2

对于第二行,我们可以把 k 放到前面。

中间两行似乎不太好化简的样子。

对于最后两行:

先根据

{x\choose y}y=x{x-1\choose y-1}

l 放到组合数里,换出一个只含 ij 的式子,提到前面去。

再将 (k-1)! 放到前面去,发现 l 的部分构成范德蒙德卷积。

\begin{aligned} \\& \sum_{k=2}^{n-1} \sum_{l=1}^{k-1} {j-2\choose k-l-1} {n-j\choose l} \ l\ (k-1)! + \sum_{k=2}^{n-1} \sum_{l=1}^{k-1} {i-1\choose l} {n-i-1\choose k-l-1} \ l\ (k-1)! \\ =& (n-j) \sum_{k=2}^{n-1} \sum_{l=1}^{k-1} {j-2\choose k-l-1} {n-j-1\choose l-1} (k-1)! + (i-1) \sum_{k=2}^{n-1} \sum_{l=1}^{k-1} {i-2\choose l-1} {n-i-1\choose k-l-1} (k-1)! \\ =& (n-j) \sum_{k=2}^{n-1} (k-1)! {n-3\choose k-2} + (i-1) \sum_{k=2}^{n-1} (k-1)! {n-3\choose k-2} \\ =& (n-j+i-1) \sum_{k=2}^{n-1} (k-1)! {n-3\choose k-2} \end{aligned}

既然最后两行化简了,那么我们就可以容斥一下,总方案减去不满足的情况(就是最后两行),从而化简了中间两行。

化简结果:(对应前面的第一行,第二行,中间两行,最后两行)

\begin{aligned} ans_n= &\frac{n(n-1)}4 \sum_{k=0}^{n-2} {n-2\choose k} (k+2)! \\+& \sum_{k=0}^{n-2} {n-2\choose k} k! \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \left( 2 \sum_{k=0}^{n-2} (k+1)! {n-2\choose k} -(n-j+i-1) \sum_{k=0}^{n-3} (k+1)! {n-3\choose k} \right) \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i<a_j] (n-j+i-1) \sum_{k=0}^{n-3} (k+1)! {n-3\choose k} \end{aligned}

这个式子里有许多类似的结构,可以把它们拿出来。

设:

\begin{aligned} f_x&=\sum_{k=0}^{x}k!{x\choose k} =\sum_{k=0}^{x}x^{\underline{k}} \\ g_x&=\sum_{k=0}^{x}(k+1)!{x\choose k} =\sum_{k=0}^{x}(k+1)x^{\underline{k}} \\ h_x&=\sum_{k=0}^{x}(k+2)!{x\choose k} =\sum_{k=0}^{x}(k+1)(k+2)x^{\underline{k}} \end{aligned}

它们都有递推式。

\begin{aligned} f_x&=1+nf_{n-1} \\ g_x&=f_x+xg_{x-1} \\ h_x&=2g_x+xh_{x-1} \end{aligned}

替换后得到

\begin{aligned} ans_n= &\frac{n(n-1)}4 h_{n-2} \\+& f_{n-2} \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] \left( 2g_{n-2}-(n-j+i-1)g_{n-3} \right) \\+& \sum_{i=1}^n \sum_{j=i+1}^n [a_i<a_j] (n-j+i-1)g_{n-3} \end{aligned}

I_n 表示 a_1\sim a_n 的逆序对数,S_n 表示 a_1\sim a_n 的逆序对的 n-j+i-1 贡献和。通过树状数组可以 O(\log n) 求出。

\begin{aligned} ans_n= &\frac{n(n-1)}4 h_{n-2}+I_nf_{n-2}+2I_ng_{n-2} \\&- \sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j] (n-j+i-1)g_{n-3} \\&+ \sum_{i=1}^n \sum_{j=i+1}^n [a_i<a_j] (n-j+i-1)g_{n-3} \\= &\frac{n(n-1)}4 h_{n-2}+I_nf_{n-2}+2I_ng_{n-2} \\&- 2S_ng_{n-3} + \sum_{i=1}^n \sum_{j=i+1}^n (n-j+i-1)g_{n-3} \end{aligned}

对于 \sum_{i=1}^n\sum_{j=i+1}^n(n-j+i-1)

\begin{aligned} &\quad\sum_{i=1}^n\sum_{j=i+1}^n(n-j+i-1) \\&=\sum_{i=1}^n\sum_{j=i+1}^n(n-j)+\sum_{i=1}^n\sum_{j=i+1}^n(i-1) \\&=\sum_{j=1}^n(j-1)(n-j)+\sum_{i=1}^n(n-j)(i-1) \\&=2\sum_{i=1}^n(n-j)(i-1) \\&=2\left(-\sum_{i=1}^ni^2+(n-1)\sum_{i=1}^ni-n^2\right) \end{aligned}
最终总复杂度为 $O(n\log n)$。 :::info[代码] ```cpp #include <bits/stdc++.h> #define ll long long #define F(i,l,r) for(ll i=l;i<=r;i++) using namespace std;const ll A=1e6+5,_=20051131; ll rd(){ll x=0,f=1;char c=getchar(); while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c))x=x*10+c-'0',c=getchar();return x*f;} ll n,a[A],f[A],g[A],h[A],ii[A],d[A],c[A],S[A],e[A]; ll chk(ll n){ ll s=h[n-2]*10025566%_*(n*(n-1)/2%_)%_; s=(s+ii[n]*f[n-2]+2*ii[n]*g[n-2])%_; s=(s+(-e[n]+n*(n+1)/2*(n+1)-n*n)%_*2*g[n-3])%_; s=(s-2*(n-1)*ii[n]%_*g[n-3]%_+2*S[n]*g[n-3]%_+_)%_; return s; } int main(){n=rd(); F(i,1,n){ll x=rd();a[i]=x; ll z=i-1; for(ll j=x;j;j-=(j&-j))z-=d[j]; for(ll j=x;j<=n;j+=(j&-j))d[j]++; ii[i]=ii[i-1]+z; S[i]=S[i-1]-(i-1)*i/2+z*i; for(ll j=x;j;j-=(j&-j))S[i]+=c[j]; for(ll j=x;j<=n;j+=(j&-j))c[j]+=i; ii[i]=(ii[i]%_+_)%_; S[i]=(S[i]%_+_)%_; } f[0]=g[0]=1,h[0]=2; F(i,1,n)f[i]=(1+i*f[i-1])%_, g[i]=(f[i]+i*g[i-1])%_, h[i]=(2*g[i]+i*h[i-1])%_, e[i]=e[i-1]+i*i; F(i,1,n)cout<<(chk(i)+f[i]*(ii[n]-ii[i]+_))%_<<"\n"; return 0; } ``` ::: 码字不易点个赞再走吧。