题意
定义一个排列a,
f
(
a
)
=
∑
i
<
j
,
且
a
i
>
a
j
(
j
−
i
)
(
a
i
−
a
j
)
f(a)=\sum_{i\lt j,且a_i>a_j}(j-i)(a_i-a_j)
f(a)=∑i<j,且ai>aj(j−i)(ai−aj)
求对于所有n的排列a,满足
a
i
̸
=
p
i
,
f
(
a
)
a_i\not=p_i,f(a)
ai̸=pi,f(a)的和,p为排列
n
≤
5000
n\leq 5000
n≤5000
题解
答案怎么算
很显然,每两个位置的贡献独立
设
f
0
(
x
)
,
f
1
(
x
)
,
f
2
(
x
)
f_0(x),f_1(x),f_2(x)
f0(x),f1(x),f2(x)分别表示n的排列,前x,x-1,x-2个位置有
a
i
̸
=
i
a_i\not=i
ai̸=i的限制,的个数
简单地说,
f
0
f_0
f0是正宗错排,
f
1
f_1
f1是少一个限制的错排,
f
2
f_2
f2是少两个限制的错排
既然这样,对于每两个位置统计对答案的贡献,对于j<i两个位置有4种摆放方式:
- { i , j } ̸ = { p i , p j } \{i,j\}\not=\{p_i,p_j\} {i,j}̸={pi,pj},这两位的答案是 ( ∑ 1 ≤ x ≤ n ∑ 1 ≤ y ≤ n ∣ x − y ∣ + ∑ 1 ≤ x ≤ n ∣ x − p i ∣ − ∑ 1 ≤ y ≤ n ∣ p j − y ∣ + a b s ( p i − p j ) ) ( i − j ) , ( 不 妨 使 大 数 放 在 左 边 小 数 放 在 右 边 ) (\sum_{1\leq x\leq n}\sum_{1\leq y\leq n}|x-y|+\sum_{1\leq x\leq n}|x-p_i|-\sum_{1\leq y\leq n}|p_j-y|+abs(p_i-p_j))(i-j),\\(不妨使大数放在左边小数放在右边) (1≤x≤n∑1≤y≤n∑∣x−y∣+1≤x≤n∑∣x−pi∣−1≤y≤n∑∣pj−y∣+abs(pi−pj))(i−j),(不妨使大数放在左边小数放在右边)化简之后就是 ( 1 6 n ( n − 1 ) ( n + 1 ) − n 2 − n − p i 2 − p j 2 + ( p i + p j ) ( n + 1 ) + ∣ p i − p j ∣ ) ( i − j ) (\frac16n(n-1)(n+1)-n^2-n-p_i^2-p_j^2+(p_i+p_j)(n+1)+|p_i-p_j|)(i-j) (61n(n−1)(n+1)−n2−n−pi2−pj2+(pi+pj)(n+1)+∣pi−pj∣)(i−j)其他的位置要乘上 f 2 ( n − 2 ) f_2(n-2) f2(n−2)的方案数
- a i = p j , a j = p i a_i=p_j,a_j=p_i ai=pj,aj=pi,答案为 max ( 0 , p i − p j ) ( i − j ) \max(0,p_i-p_j)(i-j) max(0,pi−pj)(i−j),要乘上 f 0 ( n − 2 ) f_0(n-2) f0(n−2)
- a i = p j , a j ̸ = p i a_i=p_j,a_j\not=p_i ai=pj,aj̸=pi或 a j = p i , a i ̸ = p j a_j=p_i,a_i\not=p_j aj=pi,ai̸=pj,总答案为 ( ∑ 1 ≤ x < p i p i − x + ∑ p j < y ≤ n y − p j − 2 max ( 0 , p i − p j ) ) (\sum_{1\leq x\lt p_i}p_i-x+\sum_{p_j\lt y\leq n}y-p_j-2\max(0,p_i-p_j)) (1≤x<pi∑pi−x+pj<y≤n∑y−pj−2max(0,pi−pj))化简之后就是 1 2 ( p i − 1 ) p i + 1 2 ( n − p j + 1 ) ( n − p j ) − 2 max ( 0 , p i − p j ) \frac12(p_i-1)p_i+\frac12(n-p_j+1)(n-p_j)-2\max(0,p_i-p_j) 21(pi−1)pi+21(n−pj+1)(n−pj)−2max(0,pi−pj)应该乘上 f 1 ( n − 2 ) f_1(n-2) f1(n−2)
f怎么求?
- f 0 ( n ) f_0(n) f0(n)正宗·错排数,众所周知 f 0 ( n ) = ( n − 1 ) [ f 0 ( n − 1 ) + f 0 ( n − 2 ) ] f_0(n)=(n-1)[f_0(n-1)+f_0(n-2)] f0(n)=(n−1)[f0(n−1)+f0(n−2)]
- f 1 ( n ) f_1(n) f1(n),若n放在第n为,就是n-1的错排;若n不放在第n位,故多了一个限制,是n的错排,故 f 1 ( n ) = f 0 ( n ) + f 0 ( n − 1 ) f_1(n)=f_0(n)+f_0(n-1) f1(n)=f0(n)+f0(n−1)
- f 2 ( n ) f_2(n) f2(n),和1差不多,若第n-1放n-1,第n放n,就是n-2的错排;若n放n且第n-1不放n-1,或者是第n-1放n-1且第n不放n,就相当于n-1的错排;若第n不放n,且第n-1不放n-1,就相当于n的错排,故 f 2 ( n ) = f 0 ( n ) + 2 f 0 ( n − 1 ) + f 0 ( n − 2 ) f_2(n)=f_0(n)+2f_0(n-1)+f_0(n-2) f2(n)=f0(n)+2f0(n−1)+f0(n−2)
code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i(a),_E_(b);i<=_E_;++i)
#define REP(i,a,b) for(int i(a),_E_(b);i<_E_;++i)
#define fd(i,a,b) for(int i(a),_E_(b);i>=_E_;--i)
#define pu putchar
#define ge getchar
#define mp(a,b) make_pair(a,b)
#define fs first
#define sc second
#define ll long long
#define ul unsigned long long
#define ui unsigned int
#define db double
#define ld long double
#define N 100000
#define mo 1000000009
#define ny 500000005
#define n_ 833333341
using namespace std;
void read(int &n){
n=0;int s=1;char c;for(;(c=ge())>'9'||c<'0';)if(c=='-')s=-1;
for(;c>='0'&&c<='9';c=ge())n=(n<<1)+(n<<3)+c-48;n*=s;
}
void write(int n){
if(!n)pu(48);int t=0,b[20];
for(;n;n/=10)b[++t]=n%10;while(t)pu(b[t--]+48);
}
int p[N],n;
ll f[N],ans;
ll f0(int x){return f[x];}
ll f1(int x){return ((x?f[x-1]:0)+f[x])%mo;}
ll f2(int x){return ((x>1?f[x-2]:0)+(x?2*f[x-1]:0)+f[x])%mo;}
int main(){
scanf("%d",&n);
if(n==1){
printf("0");return 0;
}
fo(i,1,n)scanf("%d",p+i);
f[0]=1;fo(i,2,n)f[i]=1ll*(i-1)*(f[i-1]+f[i-2])%mo;
fo(i,1,n)REP(j,1,i){
ll x=p[i],y=p[j];
ans=(ans+(x>y)*(x-y)*(i-j)*f0(n-2))%mo;
ans=(ans+((n-y+1)*(n-y)*ny+x*(x-1)*ny-2*(x>y)*(x-y)+mo)%mo*(i-j)%mo*f1(n-2))%mo;
ans=(ans+(1ll*n*(n+1)*(n-1)%mo*n_-n*n-n-x*x-y*y+(x+y)*(n+1)+mo+1ll*abs(x-y))%mo*(i-j)%mo*f2(n-2))%mo;
}printf("%lld",ans);
return 0;
}