Liveddd's Blog

愛にできることはまだあるかい

[ARC154E] Reverse and Inversion

拆贡献 + 推式子,对性质的观察。

拆一下贡献得到:

已知:

$(1)-(2)$ 即可得到:

所以最终 $f(p)=\sum_i i^2-i\cdot p_i$。$\sum_i i^2$ 为定值,我们相当于求 $E(\sum_i i\cdot p_i)$ 。

地第一反应是 DP,每个数的贡献显然是独立的。我们考虑计算将位置 $i$ 上的数交换到位置 $j$ 上的概率。所有状态直接构成一个矩阵,直接矩阵快速幂优化一下 就可以做到 $\mathcal O(n^3\log m)$。

注意观察从 $i\to j$ 的可行操作数为 $\min(i,j,n-i+1,n-j+1)$,这意味着 $i\to j$ 和 $i\to n-j+1$ 的概率是一样的,那么 $i$ 如果被操作了的话,那么它的期望位置就是 $\frac{n+1}{2}$。于是我们只需要分别计算 $i$ 被不被操作的概率及其期望。时间复杂度为 $\mathcal O(n\log m)$。瓶颈为快速幂。

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
#include<cstdio>
using namespace std;
const int N=2e5+10,mod=998244353,inv2=mod+1>>1;
template <class T>
inline void read(T &x)
{
x=0;int f=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();};
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(f)x=~x+1;
}
template<class T,class ...T1>
inline void read(T &x,T1 &...x1)
{
read(x),read(x1...);
}
int n,m,k,mid;
int p[N];
int ans;
inline int adj(int x){return x>=mod?x-mod:x;}
inline void upd(int &x,int y){x+=y,x=x>=mod?x-mod:x;}
inline int calc(int n){return 1ll*n*(n+1)/2%mod;}
inline int qpow(int x,int k)
{
int res=1;
while(k)
{
if(k&1)res=1ll*res*x%mod;
x=1ll*x*x%mod;
k>>=1;
}
return res;
}

int main()
{
read(n,k);
m=qpow(calc(n),k);
mid=1ll*(n+1)*inv2%mod;
for(int i=1;i<=n;i++)read(p[i]);
for(int i=1;i<=n;i++)
{
upd(ans,1ll*i*i%mod*m%mod);
int d=qpow(adj(calc(i-1)+calc(n-i)),k);
upd(ans,mod-1ll*adj(1ll*d*i%mod+1ll*adj(m-d+mod)*mid%mod)*p[i]%mod);
}
printf("%d\n",ans);
return 0;
}