P8367 [LNOI2022] 盒
题目
首先可以发现每次操作就是在前缀和数组的某一个上 +
或 -
1
1
1。所以就转换成
∑
i
=
1
n
∣
p
r
e
a
[
i
]
−
p
r
e
b
[
i
]
∣
×
w
[
i
]
\sum_{i=1}^n |pre_a[i]-pre_b[i]|\times w[i]
i=1∑n∣prea[i]−preb[i]∣×w[i]
所以最终的答案就是这个(后面的组合数表示
i
i
i 前面填的方案和
i
i
i 后面填的方案)
∑
i
=
1
n
∑
j
=
0
m
w
[
i
]
×
∣
j
−
p
r
e
[
i
]
∣
(
i
+
j
−
1
i
−
1
)
(
n
−
i
+
m
−
j
−
1
n
−
i
−
1
)
\sum_{i=1}^n\sum_{j=0}^mw[i]\times|j-pre[i]|\binom{i+j-1}{i-1}\binom{n-i+m-j-1}{n-i-1}
i=1∑nj=0∑mw[i]×∣j−pre[i]∣(i−1i+j−1)(n−i−1n−i+m−j−1)
因为绝对值很难处理,所以将绝对值符号拆开对于
j
≤
p
r
e
[
i
]
j\le pre[i]
j≤pre[i] 的情况如下,
j
>
p
r
e
[
i
]
j>pre[i]
j>pre[i] 的情况同理。
∑
j
=
0
p
r
e
[
i
]
p
r
e
[
i
]
×
(
i
+
j
−
1
i
−
1
)
(
n
−
i
+
m
−
j
−
1
n
−
i
−
1
)
−
j
×
(
i
+
j
−
1
i
−
1
)
(
n
−
i
+
m
−
j
−
1
n
−
i
−
1
)
\sum_{j=0}^{pre[i]}pre[i]\times\binom{i+j-1}{i-1}\binom{n-i+m-j-1}{n-i-1}-j\times\binom{i+j-1}{i-1}\binom{n-i+m-j-1}{n-i-1}
j=0∑pre[i]pre[i]×(i−1i+j−1)(n−i−1n−i+m−j−1)−j×(i−1i+j−1)(n−i−1n−i+m−j−1)
令
s
1
(
n
,
m
,
i
,
p
r
e
[
i
]
)
=
∑
j
=
0
p
r
e
[
i
]
(
i
+
j
−
1
i
−
1
)
(
n
−
i
+
m
−
j
−
1
n
−
i
−
1
)
s_1(n,m,i,pre[i])=\sum_{j=0}^{pre[i]}\binom{i+j-1}{i-1}\binom{n-i+m-j-1}{n-i-1}
s1(n,m,i,pre[i])=j=0∑pre[i](i−1i+j−1)(n−i−1n−i+m−j−1)
s
2
(
n
,
m
,
i
,
p
r
e
[
i
]
)
=
∑
j
=
0
p
r
e
[
i
]
j
×
(
i
+
j
−
1
i
−
1
)
(
n
−
i
+
m
−
j
−
1
n
−
i
−
1
)
s_2(n,m,i,pre[i])=\sum_{j=0}^{pre[i]}j\times\binom{i+j-1}{i-1}\binom{n-i+m-j-1}{n-i-1}
s2(n,m,i,pre[i])=j=0∑pre[i]j×(i−1i+j−1)(n−i−1n−i+m−j−1)
∴
a
n
s
=
∑
i
=
1
n
(
s
1
(
n
,
m
,
i
,
p
r
e
[
i
]
)
×
p
r
e
[
i
]
+
s
2
(
n
,
m
,
i
,
p
r
e
[
i
]
)
)
\therefore ans=\sum_{i=1}^n(s_1(n,m,i,pre[i])\times pre[i]+s_2(n,m,i,pre[i]))
∴ans=i=1∑n(s1(n,m,i,pre[i])×pre[i]+s2(n,m,i,pre[i]))
- 首先考虑
s
1
s_1
s1 如何计算。
s 1 ( n , m , x , y ) = ∑ j = 0 y ( x + j − 1 x − 1 ) ( n − x + m − j − 1 n − x − 1 ) s_1(n,m,x,y)=\sum_{j=0}^y \binom{x+j-1}{x-1}\binom{n-x+m-j-1}{n-x-1} s1(n,m,x,y)=j=0∑y(x−1x+j−1)(n−x−1n−x+m−j−1)
考虑像莫队一样处理,容易知道 ( x , y ) → ( x , y + 1 ) (x,y)\rightarrow (x,y+1) (x,y)→(x,y+1) 是容易的。
然后考虑如何从 ( x , y ) → ( x + 1 , y ) (x,y)\rightarrow(x+1,y) (x,y)→(x+1,y)。
重新考虑 s 1 s_1 s1 的组合意义,就是有 m m m 个小球, n n n 个盒子,每个盒子可以放非负个小球,并且第 [ p r e [ i ] + 1 , m ] [pre[i]+1,m] [pre[i]+1,m] 个小球必须放在 [ i + 1 , n ] [i+1,n] [i+1,n] 的盒子里的方案数。
所以枚举第 p r e [ i ] + 1 pre[i]+1 pre[i]+1 个小球的位置,然后 [ 1 , p r e [ i ] ] [1,pre[i]] [1,pre[i]] 的球放在 [ 1 , j ] [1,j] [1,j] 的盒子中; [ p r e [ i ] + 2 , m ] [pre[i]+2,m] [pre[i]+2,m] 的球放在 [ j , n ] [j,n] [j,n] 的盒子中。
方案数也就是 ∑ j = i + 1 n ( j + p r e [ i ] − 1 j − 1 ) ( n − j + m − p r e [ i ] − 1 n − j ) \sum_{j=i+1}^n \binom{j+pre[i]-1}{j-1}\binom{n-j+m-pre[i]-1}{n-j} j=i+1∑n(j−1j+pre[i]−1)(n−jn−j+m−pre[i]−1) - 然后考虑
s
2
s_2
s2 如何计算。
可以发现, j × ( i + j − 1 i − 1 ) = j × ( i + j − 1 j ) = i × ( i + j − 1 i ) j\times\binom{i+j-1}{i-1}=j\times\binom{i+j-1}{j}=i\times\binom{i+j-1}{i} j×(i−1i+j−1)=j×(ji+j−1)=i×(ii+j−1)
s 2 ( n , m , i , p r e [ i ] ) = ∑ j = 0 p r e [ i ] j × ( i + j − 1 i − 1 ) ( n − i + m − j − 1 n − i − 1 ) s_2(n,m,i,pre[i])=\sum_{j=0}^{pre[i]}j\times\binom{i+j-1}{i-1}\binom{n-i+m-j-1}{n-i-1} s2(n,m,i,pre[i])=j=0∑pre[i]j×(i−1i+j−1)(n−i−1n−i+m−j−1)
= i × ∑ j = 0 p r e [ i ] ( i + j − 1 i ) ( n − i + m − j − 1 n − i − 1 ) =i\times\sum_{j=0}^{pre[i]}\binom{i+j-1}{i}\binom{n-i+m-j-1}{n-i-1} =i×j=0∑pre[i](ii+j−1)(n−i−1n−i+m−j−1)
注意到这个式子在 j = 0 j=0 j=0 时前一个组合数的 i + j − 1 < i i+j-1<i i+j−1<i 也就无意义的,所以 j j j 整体平移 1 1 1。
= i × ∑ j = 0 p r e [ i ] − 1 ( i + j i ) ( n − i + m − j − 2 n − i − 1 ) =i\times\sum_{j=0}^{pre[i]-1}\binom{i+j}{i}\binom{n-i+m-j-2}{n-i-1} =i×j=0∑pre[i]−1(ii+j)(n−i−1n−i+m−j−2)
∴ s 2 ( n , m , i , p r e [ i ] ) = i × s 1 ( n + 1 , m − 1 , i + 1 , p r e [ i ] − 1 ) \therefore s_2(n,m,i,pre[i])=i\times s_1(n+1,m-1,i+1,pre[i]-1) ∴s2(n,m,i,pre[i])=i×s1(n+1,m−1,i+1,pre[i]−1)
另外对于之前分类讨论时同理的 j > p r e [ i ] j>pre[i] j>pre[i] 在这里丢一下 s 1 s_1 s1 的两种式子:
s 1 ( n , m , i , p r e [ i ] ) = ∑ j = p r e i + 1 m ( i + j − 1 i − 1 ) ( n − i − 1 + m − p r e i n − i − 1 ) s_1(n,m,i,pre[i])=\sum_{j=pre_i+1}^m \binom{i+j-1}{i-1} \binom{n-i-1+m-pre_i}{n-i-1} s1(n,m,i,pre[i])=j=prei+1∑m(i−1i+j−1)(n−i−1n−i−1+m−prei)
s 1 ( n , m , i , p r e [ i ] ) = ∑ j = 1 i ( j − 1 + p r e i + 1 j − 1 ) ( n − j + m − p r e i − 1 n − j ) s_1(n,m,i,pre[i])=\sum_{j=1}^i \binom{j-1+pre_i+1}{j-1} \binom{n-j+m-pre_i-1}{n-j} s1(n,m,i,pre[i])=j=1∑i(j−1j−1+prei+1)(n−jn−j+m−prei−1)
主要参考了 Kubic 的题解。
P5400 [CTS2019] 随机立方体
P10004 [集训队互测 2023] Permutation Counting 2
题目
因为有
i
i
i 个上升的位置,所以有
n
−
i
n-i
n−i 个连续上升的段
首先容斥,钦定原序列有
i
i
i 个上升段,逆序列有 j 个上升段
假设值为
f
[
i
]
[
j
]
f[i][j]
f[i][j],
a
n
s
[
i
]
[
j
]
=
∑
k
=
i
n
−
1
∑
l
=
j
n
−
1
(
−
1
)
(
k
+
l
−
i
−
j
)
×
C
(
k
,
i
)
×
C
(
l
,
j
)
×
f
[
i
]
[
j
]
ans[i][j] = \sum_{k=i}^{n-1}\sum_{l=j}^{n-1} (-1)^(k+l-i-j)\times C(k,i)\times C(l,j)\times f[i][j]
ans[i][j]=∑k=in−1∑l=jn−1(−1)(k+l−i−j)×C(k,i)×C(l,j)×f[i][j]
将逆序列中的连续段的下标往原序列中的连续段里填,可以注意到在原序列的每个连续段中所填的数始终是一个前缀 ?
所以
a
[
i
]
[
j
]
a[i][j]
a[i][j] 表示原序列的第
i
i
i 个连续段和逆序列的第
j
j
j 个连续段的交集大小
a
[
i
]
[
j
]
a[i][j]
a[i][j] 和原序列是一一对应的 ?
并且可以注意到
a
[
i
]
[
j
]
a[i][j]
a[i][j] 区别于任意的一个矩阵的限制条件是
- x x x 行 y y y 列,和为 n n n
- 矩阵内每个数都是非负整数
- 不存在一行或一列和为
0
0
0
对于第 3 个限制,再进行一个二维的二项式反演, g [ i ] [ j ] g[i][j] g[i][j] 表示钦定有 i i i 行 j j j 列和为 0 0 0, h [ i ] [ j ] h[i][j] h[i][j] 表示恰好 i i i 行 j j j 列和为 0 0 0
g [ i ] [ j ] = C ( x , i ) × C ( y , j ) × C ( n + ( x − i ) × ( y − j ) − 1 , ( x − i ) × ( y − j ) − 1 ) g[i][j] = C(x,i)\times C(y,j)\times C(n+(x-i)\times(y-j)-1,(x-i)\times(y-j)-1) g[i][j]=C(x,i)×C(y,j)×C(n+(x−i)×(y−j)−1,(x−i)×(y−j)−1)
g [ i ] [ j ] = ∑ a = i x ∑ b = j y C ( a , i ) × C ( b , j ) × h [ a ] [ b ] g[i][j] = \sum_{a=i}^x \sum_{b=j}^y C(a,i)\times C(b,j)\times h[a][b] g[i][j]=∑a=ix∑b=jyC(a,i)×C(b,j)×h[a][b]
h [ i ] [ j ] = ∑ a = i x ∑ b = j y ( − 1 ) a + b − i − j C ( a , i ) × C ( b , j ) × g [ a ] [ b ] h[i][j] = \sum_{a=i}^x \sum_{b=j}^y (-1)^{a+b-i-j} C(a,i)\times C(b,j)\times g[a][b] h[i][j]=∑a=ix∑b=jy(−1)a+b−i−jC(a,i)×C(b,j)×g[a][b]
f [ x ] [ y ] = h [ 0 ] [ 0 ] f[x][y] = h[0][0] f[x][y]=h[0][0]
上面的时间复杂度是 O ( n 4 ) O(n^4) O(n4) 的
但注意到二项式反演的两维互不影响,所以分开做,是 O ( n 3 ) O(n^3) O(n3) 的。
参考了 Nesraychan QOJ 上的代码的取模优化。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#define ull unsigned long long
using namespace std;
const int N=505;
int n,mod;
ull qwq;
int fac[N*N],inv[N*N],ifac[N*N],tmp[N],g[N][N],f[N][N],ans[N][N];
inline int read()
{
int s=0,t=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s*t;
}
inline int fastmod(ull a)
{
ull awa=((__uint128_t)a*qwq)>>64;
int rest=a-awa*mod;
return (rest<mod?rest:rest-mod);
}
inline int add(int a,int b){return (a+b>=mod?a+b-mod:a+b);}
inline int del(int a,int b){return (a-b<0?a-b+mod:a-b);}
inline int mul(int a,int b){return (1ull*a*b<mod?a*b:fastmod(1ull*a*b));}
inline void init(int n)
{
fac[0]=inv[0]=ifac[0]=fac[1]=inv[1]=ifac[1]=1;
for(int i=2;i<=n;++i)
{
fac[i]=mul(fac[i-1],i);
inv[i]=mul((mod-mod/i),inv[mod%i]);
ifac[i]=mul(ifac[i-1],inv[i]);
}
return;
}
inline int C(int n,int m)
{
if(n<0||m<0||n-m<0) return 0;
return mul(mul(fac[n],ifac[m]),ifac[n-m]);
}
int main()
{
n=read();
mod=read();
qwq=((__uint128_t)1<<64)/mod;
init(n*(n+5));
for(int y=1;y<=n;++y)
{
for(int i=0;i<=n;++i)
{
tmp[i]=0;
for(int j=0;j<=y;++j)
{
int sig=y-j;
if(sig&1) tmp[i]=del(tmp[i],mul(C(y,j),C(n+i*j-1,i*j-1)));
else tmp[i]=add(tmp[i],mul(C(y,j),C(n+i*j-1,i*j-1)));
}
}
for(int x=1;x<=n;++x)
{
int val=0;
for(int i=0;i<=x;++i)
{
int sig=x-i;
if(sig&1) val=del(val,mul(C(x,i),tmp[i]));
else val=add(val,mul(C(x,i),tmp[i]));
}
f[n-y][n-x]=val;
}
}
for(int y=0;y<=n-1;++y)
{
for(int i=0;i<=n-1;++i)
{
tmp[i]=0;
for(int j=y;j<=n-1;++j)
{
int sig=j-y;
if(sig&1) tmp[i]=del(tmp[i],mul(C(j,y),f[j][i]));
else tmp[i]=add(tmp[i],mul(C(j,y),f[j][i]));
}
}
for(int x=0;x<=n-1;++x)
for(int i=x;i<=n-1;++i)
{
int sig=i-x;
if(sig&1) ans[y][x]=del(ans[y][x],mul(C(i,x),tmp[i]));
else ans[y][x]=add(ans[y][x],mul(C(i,x),tmp[i]));
}
}
for(int i=0;i<=n-1;++i)
for(int j=0;j<=n-1;++j)
printf("%d%c",ans[j][i]," \n"[j==n-1]);
return 0;
}