简单的数据结构题
首先考虑计算要求的式子,不妨设l=1,r=nl=1,r=nl=1,r=n。
∑i=1naik∏j≠i1−aiajai−aj\sum_{i=1}^{n}a_i^k\prod_{j\not=i}\frac{1-a_ia_j}{a_i-a_j}∑i=1naik∏j=iai−aj1−aiaj
=∑i=1naik∏j≠i1ai−aj∏j≠i(1−aiaj)=\sum_{i=1}^{n}a_i^k\prod_{j\not=i}\frac{1}{a_i-a_j}\prod_{j\not=i}(1-a_ia_j)=∑i=1naik∏j=iai−aj1∏j=i(1−aiaj)
=∑i=1naik∏j≠i1ai−aj∑l=0n−1[xn−1−l]∏j≠i(x−aiaj)=\sum_{i=1}^{n}a_i^k\prod_{j\not=i}\frac{1}{a_i-a_j}\sum_{l=0}^{n-1}[x^{n-1-l}]\prod_{j\not=i}(x-a_ia_j)=∑i=1naik∏j=iai−aj1∑l=0n−1[xn−1−l]∏j=i(x−aiaj)
=∑i=1naik∏j≠i1ai−aj∑l=0n−1ail[xn−1−l]∏j≠i(x−aj)=\sum_{i=1}^{n}a_i^k\prod_{j\not=i}\frac{1}{a_i-a_j}\sum_{l=0}^{n-1}a_i^l[x^{n-1-l}]\prod_{j\not=i}(x-a_j)=∑i=1naik∏j=iai−aj1∑l=0n−1ail[xn−1−l]∏j=i(x−aj)
=∑l=0n−1∑i=1naik+l∏j≠i1ai−aj[xn−1−l]∏j≠i(x−aj)=\sum_{l=0}^{n-1}\sum_{i=1}^{n}a_i^{k+l}\prod_{j\not=i}\frac{1}{a_i-a_j}[x^{n-1-l}]\prod_{j\not=i}(x-a_j)=∑l=0n−1∑i=1naik+l∏j=iai−aj1[xn−1−l]∏j=i(x−aj)
=∑l=0n−1∑i=1n[xn−1−l](aik+l∏j≠i1ai−aj)x0∏j≠i(x−aj)=\sum_{l=0}^{n-1}\sum_{i=1}^{n}[x^{n-1-l}](a_i^{k+l}\prod_{j\not=i}\frac{1}{a_i-a_j})x^0\prod_{j\not=i}(x-a_j)=∑l=0n−1∑i=1n[xn−1−l](aik+l∏j=iai−aj1)x0∏j=i(x−aj)
=∑l=0n−1∑i=1n[xn−1−l]aik+l∏j≠ix−ajai−aj=\sum_{l=0}^{n-1}\sum_{i=1}^{n}[x^{n-1-l}]a_i^{k+l}\prod_{j\not=i}\frac{x-a_j}{a_i-a_j}=∑l=0n−1∑i=1n[xn−1−l]aik+l∏j=iai−ajx−aj
=∑l=0n−1[xn−1−l]∑i=1naik+l∏j≠ix−ajai−aj=\sum_{l=0}^{n-1}[x^{n-1-l}]\sum_{i=1}^{n}a_i^{k+l}\prod_{j\not=i}\frac{x-a_j}{a_i-a_j}=∑l=0n−1[xn−1−l]∑i=1naik+l∏j=iai−ajx−aj
根据拉格朗日插值:
f(x)f(x)f(x)是一个过点(x1,y1),(x2,y2),...,(xn,yn)的函数(x_1,y_1),(x_2,y_2),...,(x_n,y_n)的函数(x1,y1),(x2,y2),...,(xn,yn)的函数
记M=∏i=1n(x−xi)M=\prod_{i=1}^{n}(x-x_i)M=∏i=1n(x−xi),则
f(x)≡∑i=1nyi∏j≠ix−xjxi−xj(modM)f(x)\equiv \sum_{i=1}^{n}y_i\prod_{j\not=i}\frac{x-x_j}{x_i-x_j}(mod\space M)f(x)≡∑i=1nyi∏j=ixi−xjx−xj(mod M)
函数f(x)=xk+lf(x)=x^{k+l}f(x)=xk+l过点(a1,a1k+l),(a2,a2k+l),...,(an,ank+l)(a_1,a_1^{k+l}),(a_2,a_2^{k+l}),...,(a_n,a_n^{k+l})(a1,a1k+l),(a2,a2k+l),...,(an,ank+l)
∴xk+l≡∑i=1naik+l∏j≠ix−ajai−aj(mod(x−a1)(x−a2)...(x−an))\therefore x^{k+l}\equiv\sum_{i=1}^{n}a_i^{k+l}\prod_{j\not=i}\frac{x-a_j}{a_i-a_j}(mod\space(x-a_1)(x-a_2)...(x-a_n))∴xk+l≡∑i=1naik+l∏j=iai−ajx−aj(mod (x−a1)(x−a2)...(x−an))
∴原式=∑l=0n−1[xn−1−l](xk+lmod(x−a1)(x−a2)...(x−an))\therefore原式=\sum_{l=0}^{n-1}[x^{n-1-l}](x^{k+l}\mod(x-a_1)(x-a_2)...(x-a_n))∴原式=∑l=0n−1[xn−1−l](xk+lmod(x−a1)(x−a2)...(x−an))
注意到0≤k≤20\leq k\leq20≤k≤2,且l≤n−1l\leq n-1l≤n−1,所以k+l≥nk+l\geq nk+l≥n的情况不多,分类讨论即可:
1.若k+l≤n−1k+l\leq n-1k+l≤n−1(xk+lx^{k+l}xk+l的次数低于modmodmod的多项式):
原式=∑l=1n−1[xn−1−l]xk+l=∑l=1n−1[n−1−l=k+l]原式=\sum_{l=1}^{n-1}[x^{n-1-l}]x^{k+l}=\sum_{l=1}^{n-1}[n-1-l=k+l]原式=∑l=1n−1[xn−1−l]xk+l=∑l=1n−1[n−1−l=k+l]
解得l=n−k−12l=\frac{n-k-1}{2}l=2n−k−1
则当n−k−1≡0(mod2)n-k-1\equiv 0(mod\space 2)n−k−1≡0(mod 2)且0≤n−k−10\leq n-k-10≤n−k−1时原式为1,否则为0,
即当n−k−1≡1(mod2)n-k-1\equiv1(mod\space 2)n−k−1≡1(mod 2)或n=1,k=2n=1,k=2n=1,k=2时原式为0,否则为1
2.若k+l≥nk+l\geq nk+l≥n:
∵l≤n−1\because l\leq n-1∵l≤n−1 ∴k≥1\therefore k\geq1∴k≥1
2.1若k=1k=1k=1:
此时有l=n−1l=n-1l=n−1
原式=[x0](xnmod(x−a1)(x−a2)...(x−an))原式=[x^0](x^n\mod(x-a_1)(x-a_2)...(x-a_n))原式=[x0](xnmod(x−a1)(x−a2)...(x−an))
=[x0](xn−(x−a1)(x−a2)...(x−an))=[x^0](x^n-(x-a_1)(x-a_2)...(x-a_n))=[x0](xn−(x−a1)(x−a2)...(x−an))
=(−1)n+1a1a2...an=(-1)^{n+1}a_1a_2...a_n=(−1)n+1a1a2...an
2.2若k=2k=2k=2:
此时有l=n−2或l=n−1l=n-2或l=n-1l=n−2或l=n−1
2.2.1若 l=n−2l=n-2l=n−2:
∵l≥0\because l\geq0∵l≥0 ∴n≠1\therefore n\not=1∴n=1
原式=[x1](xnmod(x−a1)(x−a2)...(x−an))原式=[x^1](x^n\mod(x-a_1)(x-a_2)...(x-a_n))原式=[x1](xnmod(x−a1)(x−a2)...(x−an))
=[x1](xn−(x−a1)(x−a2)...(x−an))=[x^1](x^n-(x-a_1)(x-a_2)...(x-a_n))=[x1](xn−(x−a1)(x−a2)...(x−an))
=(−1)n∑i=1n∏j≠iaj=(-1)^n\sum_{i=1}^{n}\prod_{j\not=i}a_j=(−1)n∑i=1n∏j=iaj
2.2.2若 l=n−1l=n-1l=n−1:
原式=[x0](xn+1mod(x−a1)(x−a2)...(x−an))原式=[x^0](x^{n+1}\mod(x-a_1)(x-a_2)...(x-a_n))原式=[x0](xn+1mod(x−a1)(x−a2)...(x−an))
=[x0](xn+1−(x+a1+a2+...+an)⏟大除法得出(x−a1)(x−a2)...(x−an))=[x^0](x^{n+1}-\begin{matrix}\underbrace{(x+a_1+a_2+...+a_n)}\\大除法得出\end{matrix}(x-a_1)(x-a_2)...(x-a_n))=[x0](xn+1−(x+a1+a2+...+an)大除法得出(x−a1)(x−a2)...(x−an))
=(−1)n+1∑i=1nai∏j=1naj=(-1)^{n+1}\sum_{i=1}^{n}a_i\prod_{j=1}^{n}a_j=(−1)n+1∑i=1nai∏j=1naj
当n=1,k=2n=1,k=2n=1,k=2时,两处的特判可以相互抵消,于是可以不需要特判。
于是只要维护∑i=1nai\sum_{i=1}^{n}a_i∑i=1nai ,∏i=1nai\prod_{i=1}^{n}a_i∏i=1nai ,∑i=1n∏j≠iaj\sum_{i=1}^{n}\prod_{j\not=i}a_j∑i=1n∏j=iaj,在区间乘的操作下用线段树解决
#include<iostream>
#include<cstdio>
using namespace std;
const int mod=998244353;
const int N=300010;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
struct Node{int sum,pro,ans;Node(){sum=0;pro=1;ans=0;}Node(int a,int b,int c){sum=a,pro=b,ans=c;}
}t[N<<2];
int n,m,a[N],laz[N<<2];
int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
int mul(int a,int b){return 1ll*a*b%mod;}
int power(int a,int b){int res=1;while(b){if(b&1) res=mul(res,a);a=mul(a,a);b>>=1;}return res;
}
Node merge(Node a,Node b){Node c;c.sum=add(a.sum,b.sum);c.pro=mul(a.pro,b.pro);c.ans=add(mul(a.ans,b.pro),mul(a.pro,b.ans));return c;
}
void pushup(int u){t[u]=merge(t[u<<1],t[u<<1|1]);
}
void build(int u,int l,int r){laz[u]=1;if(l==r){t[u]=Node(a[l],a[l],1);return;}int mid=(l+r)>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void modify(int u,int l,int r,int x){t[u].sum=mul(t[u].sum,x);t[u].pro=mul(t[u].pro,power(x,r-l+1));t[u].ans=mul(t[u].ans,power(x,r-l));laz[u]=mul(laz[u],x);
}
void pushdown(int u,int l,int r){if(laz[u]!=1){int mid=(l+r)>>1;modify(u<<1,l,mid,laz[u]);modify(u<<1|1,mid+1,r,laz[u]);laz[u]=1;}
}
void update(int u,int l,int r,int a,int b,int x){if(a<=l&&r<=b){modify(u,l,r,x);return;}pushdown(u,l,r);int mid=(l+r)>>1;if(a<=mid) update(u<<1,l,mid,a,b,x);if(b>mid) update(u<<1|1,mid+1,r,a,b,x);pushup(u);
}
Node query(int u,int l,int r,int a,int b){if(a<=l&&r<=b) return t[u];pushdown(u,l,r);int mid=(l+r)>>1;Node res=Node(0,1,0);if(a<=mid) res=merge(res,query(u<<1,l,mid,a,b));if(b>mid) res=merge(res,query(u<<1|1,mid+1,r,a,b));return res;
}
int main(){n=read();m=read();for(int i=1;i<=n;i++) a[i]=read();build(1,1,n);int opt,l,r,k;while(m--){opt=read();l=read();r=read();k=read();if(opt==1)update(1,1,n,l,r,k);else{int d=r-l+1,ans=0;if(!((d-k-1)&1)) ans++;Node now=query(1,1,n,l,r);if(k==1){if(d&1) ans=add(ans,now.pro);else ans=dec(ans,now.pro);}if(k==2){if(!(d&1)) ans=add(ans,now.ans);else ans=dec(ans,now.ans);if(d&1) ans=add(ans,mul(now.sum,now.pro));else ans=dec(ans,mul(now.sum,now.pro));}printf("%d\n",ans);}}return 0;
}