0
点赞
收藏
分享

微信扫一扫

【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)

杨小羊_ba17 2022-07-12 阅读 23

【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数

给你一个 【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_02 的矩阵,行列从 1 开始标号,第 i 行 j 列的值是 【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_03
现在要求你实现以下操作。

  • 交换两行。
  • 交换两列。
  • 求一个子矩阵的做 k 次前缀和之后的和,对【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_04取模

【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_05

  • 题解
    首先【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_06表示的数为【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_07,那么可以看成是【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_08,这样交换两行或是两列就是【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_09数组中简单的交换
    考虑一个点对整个和的贡献,这个贡献就是从【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_10每次朝【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_11可以是本身的方向走【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_12步到【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_13的概率,发现【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_14依然是独立的,那么方案数可以看成【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_15
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_16
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_17
    其中【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_18,可以列求和,那么现在的问题就是快速求这么一个东西:
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_19
    一个套路是把组合数转成下降幂再转自然幂
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_20
    然后用【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_21化简
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_22
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_23
    【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_24
    发现我们可以【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_git_25处理出【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_26的系数,那么我们用数据结构维护【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_i++_27就可以了
    单点修改区间查询,练了一波【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_28线段树
    询问复杂度【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_29

比较巧妙的地方是对 【省选模拟】矩阵求和(斯特林数)(组合数转下降幂)(ZKW线段树)_组合数_30 分别考虑,不好直接维护的东西转成多项式维护每一项的系数

#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
cs int N = 1e5 + 50, K = 15;
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans,a); return ans; }
void Add(int &a, int b){ a = add(a, b); }
void Dec(int &a, int b){ a = dec(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
int sgn(int a){ return a & 1 ? Mod - 1 : 1; }
int n, m, q, A[N], B[N];
int C[K][K], S[K][K], fac[N], ifac[N];
int Binom(int n, int m){ if(n<0||m<0||n<m) return 0; return mul(fac[n],mul(ifac[n-m],ifac[m])); }
void prework(int n, int m){
C[0][0] = S[0][0] = fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
for(int i = 2; i <= m; i++) fac[i] = mul(fac[i-1], i);
ifac[m] = ksm(fac[m], Mod-2);
for(int i = m-1; i >= 2; i--) ifac[i] = mul(ifac[i+1], i+1);
for(int i = 1; i <= n; i++){
C[i][0] = 1;
for(int j = 1; j <= i; j++) C[i][j] = add(C[i-1][j], C[i-1][j-1]);
for(int j = 1; j <= i; j++) S[i][j] = add(S[i-1][j-1], mul(i-1, S[i-1][j]));
}
}
struct ZKW{
int vl[N<<2], M;
void build(int *a, int deg){
for(M=1;M<=deg;M<<=1);
for(int i=M+1; i<=M+deg; i++) vl[i]=a[i-M];
for(int i=M-1; i; i--) vl[i] = add(vl[i<<1], vl[i<<1|1]);
}
void modify(int x, int v){
vl[x+=M] = v;
for(x>>=1; x; x>>=1) vl[x] = add(vl[x<<1], vl[x<<1|1]);
}
int query(int l, int r){
int ans = 0;
for(l+=M-1,r+=M+1; l^r^1; l>>=1, r>>=1){
if(l&1^1) Add(ans, vl[l^1]);
if(r&1) Add(ans, vl[r^1]);
} return ans;
}
}Tx[11], Ty[11];
void build(){
static int a[N], b[N];
for(int i = 1; i <= n; i++) a[i] = A[i] = mul(i-1, m);
for(int i = 1; i <= m; i++) b[i] = B[i] = i;
for(int x = 0; x <= 10; x++){
Tx[x].build(a, n);
Ty[x].build(b, m);
for(int i = 1; i <= n; i++) Mul(a[i],dec(0,i));
for(int i = 1; i <= m; i++) Mul(b[i],dec(0,i));
}
}
int query(){
static int coe_x[K], coe_y[K];
memset(coe_x, 0, sizeof(coe_x));
memset(coe_y, 0, sizeof(coe_y));
int x1 = read(), y1 = read(), x2 = read(), y2 = read(), k = read();
for(int i = 0; i <= k; i++){
int coe = mul(ifac[k], mul(sgn(k-i), S[k][i]));
for(int j = 0, px = 1, py = 1; j <= i; j++, Mul(px, x2+k), Mul(py, y2+k)){
Add(coe_x[i-j], mul(coe, mul(C[i][j],px)));
Add(coe_y[i-j], mul(coe, mul(C[i][j],py)));
}
}
int Sx0 = 0, Sx1 = 0, Sy0 = 0, Sy1 = 0;
for(int i = 0; i <= k; i++){
Add(Sx1, mul(Tx[i].query(x1,x2), coe_x[i]));
Add(Sy1, mul(Ty[i].query(y1,y2), coe_y[i]));
} Sx0 = Binom(x2-x1+k+1, k+1); Sy0 = Binom(y2-y1+k+1,k+1);
int ans = add(mul(Sx0,Sy1),mul(Sy0,Sx1));
cout << ans << '\n';
}
void Swap_row(){
int x = read(), y = read();
swap(A[x], A[y]);
for(int i = 0, coe_x = 1, coe_y = 1; i <= 10; i++){
Tx[i].modify(x, mul(A[x],coe_x));
Tx[i].modify(y, mul(A[y],coe_y));
Mul(coe_x, dec(0,x)); Mul(coe_y, dec(0,y));
}
}
void Swap_clm(){
int x = read(), y = read();
swap(B[x], B[y]);
for(int i = 0, coe_x = 1, coe_y = 1; i <= 10; i++){
Ty[i].modify(x, mul(B[x],coe_x));
Ty[i].modify(y, mul(B[y],coe_y));
Mul(coe_x, dec(0,x)); Mul(coe_y, dec(0,y));
}
}
int main(){
n = read(), m = read(), q = read();
prework(10, 1e5 + 10);
build(); char op[3];
while(q--){
scanf("%s", op);
if(op[0] == 'Q') query();
if(op[0] == 'R') Swap_row();
if(op[0] == 'C') Swap_clm();
} return 0;
}


举报

相关推荐

0 条评论