SCP-J 2026 T4

· · 题解

Solution

看到这一题一开始以为是数据结构题,然而其实是数学题。

不妨对 A_0 求其差分数组 D,然后由于显然 A_k 为差分数组 D 的 k+1 阶前缀和,能得到:

A_{k,j}=\sum^{j}_{i=1}D_i\binom{j-i+k}{k}

反过来,D 数组就是 A_k 数组的 k+1 阶差分:

D_i=\sum^{k+1}_{j=0}(-1)^{j}\binom{k+1}{j}A_{k,i-j}

对于操作 1 中对 A_x 的修改,我们可以引入一个数列 d,表示 A_x 数组的增量数组的一阶差分。很容易得出只有 d_l=k 和 d_{r+1}=-k,其他项都是 0。把它做 x 阶差分,得到数列 d':

d'_i=\sum^{x}_{j=0}(-1)^{j}\binom{x}{j}d_{i-j}

因为 d 中很多项都是 0,最后我们化简会得到(下面 i 是介于 0 和 x 之间的整数):

d'_{l+i}=k\binom{x}{i}(-1)^i d'_{r+i+1}=-k\binom{x}{i}(-1)^i

当然 d' 除了上述项,其他项都是 0。

只需拿 d' 去更新 D,就完成了操作 1。

对于操作 2 就简单了。利用组合恒等式 \sum_{j=i}^{r}\binom{j-i+x}{x}=\binom{r-i+x+1}{x+1},可以对所求式子进行一些转化:

\begin{aligned} &\sum^{r}_{j=l}A_{x,j}\\ &=\sum^{r}_{j=l}\sum^{j}_{i=1}D_i\binom{j-i+x}{x}\\ &=\sum^{r}_{i=1}D_i\sum^{r}_{j=\max(i,l)} \binom{j-i+x}{x}\\ &=\sum^{r}_{i=1}D_i\left( \sum_{j=i}^r \binom{j-i+x}{x} -\sum_{j=i}^{l-1}\binom{j-i+x}{x} \right)\\ &=\sum_{i=1}^{r}D_i\left[\binom{r-i+x+1}{x+1}-\binom{l-1-i+x+1}{x+1}\right]\\ \end{aligned}

这样就化成了可做的形式。

:::success[AC code & 提交记录] 代码由赛后整理。 ```cpp //edit by devc++ //by gitxiaozheng/dakada //我还以为是ds #include<bits/stdc++.h> using namespace std; #define L long long #define iotype L //zigai #define space putchar(' ') #define enter putchar('\n') inline iotype qcin(); void qcout(iotype); const L mod=1e9+7,maxn=310,maxpq=1e5+10; int tot=0; L Jc[maxn*2],Jcinv[maxn*2]; int diff[maxn]; int a[maxn]; L qpow(L a,L b){ L res=1,base=a; while(b){ if(b&1){ res=(base*res)%mod; } base=(base*base)%mod; b>>=1; } return res; } void predone(int n){ Jc[0]=1; for(L i=1;i<=n;i++){ Jc[i]=(Jc[i-1]*i)%mod; } Jcinv[n]=qpow(Jc[n],mod-2); for(L i=n-1;i>=0;i--){ Jcinv[i]=(Jcinv[i+1]*(i+1))%mod; } } L C(L n,L m){ if(m<0||m>n||n<0)return 0; return ((Jc[n]*Jcinv[m])%mod*Jcinv[n-m])%mod; } void add(int x,int l,int r,L k,int n){ for(int i=0;i<=x;i++){ L val=((k*C(x,i))%mod*(i&1?-1:1)+mod)%mod; int a1=l+i,b1=r+i+1; if(a1<=n){ diff[a1]=((diff[a1]+val)+mod)%mod; } if(b1<=n){ diff[b1]=((diff[b1]-val)+mod)%mod; } } } L query(int x,int l,int r,int n){ L res=0; for(int i=1;i<=r;i++){ if(!diffs[i])continue; res=(res+(1ll*diff[i]*(C(r-i+x+1,x+1)-C(l-1-i+x+1,x+1)+mod)%mod)%mod)%mod; } return res; } signed main(){ //Your code is here... int n=qcin(),p=qcin(),q=qcin(); predone(n*2+10); for(int i=1;i<=n;i++){ a[i]=(qcin()+mod)%mod; diff[i]=(a[i]-a[i-1]+mod)%mod; } for(int Q=p+q;Q;Q--){ int op=qcin(),x=qcin(),l=qcin(),r=qcin(); if(op==1){ L k=(qcin()+mod)%mod; add(x,l,r,k,n); }else{ qcout(query(x,l,r,n)); enter; } } return 0; } inline iotype qcin(){ iotype k=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-'){ f=-1; } c=getchar(); } while(c>='0'&&c<='9'){ k=k*10+c-'0'; c=getchar(); } return k*f; } void qcout(iotype x){ static int num[20]; int tot=0; if(x<0){ putchar('-'); x=-x; } while(x>=10){ num[++tot]=x%10; x/=10; } putchar(x+'0'); for(int i=tot;i>=1;i--){ putchar(num[i]+'0'); } } ``` [提交记录](https://www.luogu.com.cn/record/303930616)。 :::