种花(derangement)

题意


定义一个排列a, f ( a ) = ∑ i &lt; j , 且 a i &gt; a j ( j − i ) ( a i − a j ) f(a)=\sum_{i\lt j,且a_i&gt;a_j}(j-i)(a_i-a_j) f(a)=i<j,ai>aj(ji)(aiaj)
求对于所有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 n5000


题解


答案怎么算

很显然,每两个位置的贡献独立
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种摆放方式:

  1. { 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),\\(不妨使大数放在左边小数放在右边) (1xn1ynxy+1xnxpi1ynpjy+abs(pipj))(ij)(使)化简之后就是 ( 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(n1)(n+1)n2npi2pj2+(pi+pj)(n+1)+pipj)(ij)其他的位置要乘上 f 2 ( n − 2 ) f_2(n-2) f2(n2)的方案数
  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,pipj)(ij),要乘上 f 0 ( n − 2 ) f_0(n-2) f0(n2)
  3. 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 &lt; p i p i − x + ∑ p j &lt; 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)) (1x<pipix+pj<ynypj2max(0,pipj))化简之后就是 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(pi1)pi+21(npj+1)(npj)2max(0,pipj)应该乘上 f 1 ( n − 2 ) f_1(n-2) f1(n2)
f怎么求?
  1. 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)=(n1)[f0(n1)+f0(n2)]
  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(n1)
  3. 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(n1)+f0(n2)

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值