简单的数据结构题(多项式、拉格朗日插值、线段树)

简单的数据结构题

首先考虑计算要求的式子,不妨设 l = 1 , r = n l=1,r=n l=1,r=n

∑ i = 1 n a i k ∏ j ≠ i 1 − a i a j a i − a j \sum_{i=1}^{n}a_i^k\prod_{j\not=i}\frac{1-a_ia_j}{a_i-a_j} i=1naikj=iaiaj1aiaj

= ∑ i = 1 n a i k ∏ j ≠ i 1 a i − a j ∏ j ≠ i ( 1 − a i a j ) =\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=1naikj=iaiaj1j=i(1aiaj)

= ∑ i = 1 n a i k ∏ j ≠ i 1 a i − a j ∑ l = 0 n − 1 [ x n − 1 − l ] ∏ j ≠ i ( x − a i a j ) =\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=1naikj=iaiaj1l=0n1[xn1l]j=i(xaiaj)

= ∑ i = 1 n a i k ∏ j ≠ i 1 a i − a j ∑ l = 0 n − 1 a i l [ x n − 1 − l ] ∏ j ≠ i ( x − a j ) =\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=1naikj=iaiaj1l=0n1ail[xn1l]j=i(xaj)

= ∑ l = 0 n − 1 ∑ i = 1 n a i k + l ∏ j ≠ i 1 a i − a j [ x n − 1 − l ] ∏ j ≠ i ( x − a j ) =\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=0n1i=1naik+lj=iaiaj1[xn1l]j=i(xaj)

= ∑ l = 0 n − 1 ∑ i = 1 n [ x n − 1 − l ] ( a i k + l ∏ j ≠ i 1 a i − a j ) x 0 ∏ j ≠ i ( x − a j ) =\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=0n1i=1n[xn1l](aik+lj=iaiaj1)x0j=i(xaj)

= ∑ l = 0 n − 1 ∑ i = 1 n [ x n − 1 − l ] a i k + l ∏ j ≠ i x − a j a i − a j =\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=0n1i=1n[xn1l]aik+lj=iaiajxaj

= ∑ l = 0 n − 1 [ x n − 1 − l ] ∑ i = 1 n a i k + l ∏ j ≠ i x − a j a i − a j =\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=0n1[xn1l]i=1naik+lj=iaiajxaj


根据拉格朗日插值

f ( x ) f(x) f(x)是一个过点 ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) 的 函 数 (x_1,y_1),(x_2,y_2),...,(x_n,y_n)的函数 (x1,y1),(x2,y2),...,(xn,yn)

M = ∏ i = 1 n ( x − x i ) M=\prod_{i=1}^{n}(x-x_i) M=i=1n(xxi),则

f ( x ) ≡ ∑ i = 1 n y i ∏ j ≠ i x − x j x i − x j ( m o d   M ) 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=1nyij=ixixjxxj(mod M)


函数 f ( x ) = x k + l f(x)=x^{k+l} f(x)=xk+l过点 ( a 1 , a 1 k + l ) , ( a 2 , a 2 k + l ) , . . . , ( a n , a n k + 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)

∴ x k + l ≡ ∑ i = 1 n a i k + l ∏ j ≠ i x − a j a i − a j ( m o d   ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) \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+li=1naik+lj=iaiajxaj(mod (xa1)(xa2)...(xan))

∴ 原 式 = ∑ l = 0 n − 1 [ x n − 1 − l ] ( x k + l m o d    ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) \therefore原式=\sum_{l=0}^{n-1}[x^{n-1-l}](x^{k+l}\mod(x-a_1)(x-a_2)...(x-a_n)) =l=0n1[xn1l](xk+lmod(xa1)(xa2)...(xan))


注意到 0 ≤ k ≤ 2 0\leq k\leq2 0k2,且 l ≤ n − 1 l\leq n-1 ln1,所以 k + l ≥ n k+l\geq n k+ln的情况不多,分类讨论即可:

1.若 k + l ≤ n − 1 k+l\leq n-1 k+ln1 x k + l x^{k+l} xk+l的次数低于 m o d mod mod的多项式):

原 式 = ∑ l = 1 n − 1 [ x n − 1 − l ] x k + l = ∑ l = 1 n − 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=1n1[xn1l]xk+l=l=1n1[n1l=k+l]

解得 l = n − k − 1 2 l=\frac{n-k-1}{2} l=2nk1

则当 n − k − 1 ≡ 0 ( m o d   2 ) n-k-1\equiv 0(mod\space 2) nk10(mod 2) 0 ≤ n − k − 1 0\leq n-k-1 0nk1时原式为1,否则为0,
即当 n − k − 1 ≡ 1 ( m o d   2 ) n-k-1\equiv1(mod\space 2) nk11(mod 2) n = 1 , k = 2 n=1,k=2 n=1,k=2时原式为0,否则为1

2.若 k + l ≥ n k+l\geq n k+ln

∵ l ≤ n − 1 \because l\leq n-1 ln1 ∴ k ≥ 1 \therefore k\geq1 k1

2.1若 k = 1 k=1 k=1

此时有 l = n − 1 l=n-1 l=n1

原 式 = [ x 0 ] ( x n m o d    ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) 原式=[x^0](x^n\mod(x-a_1)(x-a_2)...(x-a_n)) =[x0](xnmod(xa1)(xa2)...(xan))
= [ x 0 ] ( x n − ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) =[x^0](x^n-(x-a_1)(x-a_2)...(x-a_n)) =[x0](xn(xa1)(xa2)...(xan))
= ( − 1 ) n + 1 a 1 a 2 . . . a n =(-1)^{n+1}a_1a_2...a_n =(1)n+1a1a2...an

2.2若 k = 2 k=2 k=2

此时有 l = n − 2 或 l = n − 1 l=n-2或l=n-1 l=n2l=n1

2.2.1若 l = n − 2 l=n-2 l=n2

∵ l ≥ 0 \because l\geq0 l0 ∴ n ≠ 1 \therefore n\not=1 n=1

原 式 = [ x 1 ] ( x n m o d    ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) 原式=[x^1](x^n\mod(x-a_1)(x-a_2)...(x-a_n)) =[x1](xnmod(xa1)(xa2)...(xan))
= [ x 1 ] ( x n − ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) =[x^1](x^n-(x-a_1)(x-a_2)...(x-a_n)) =[x1](xn(xa1)(xa2)...(xan))
= ( − 1 ) n ∑ i = 1 n ∏ j ≠ i a j =(-1)^n\sum_{i=1}^{n}\prod_{j\not=i}a_j =(1)ni=1nj=iaj

2.2.2若 l = n − 1 l=n-1 l=n1

原 式 = [ x 0 ] ( x n + 1 m o d    ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) 原式=[x^0](x^{n+1}\mod(x-a_1)(x-a_2)...(x-a_n)) =[x0](xn+1mod(xa1)(xa2)...(xan))
= [ x 0 ] ( x n + 1 − ( x + a 1 + a 2 + . . . + a n ) ⏟ 大 除 法 得 出 ( x − a 1 ) ( x − a 2 ) . . . ( x − a n ) ) =[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)(xa1)(xa2)...(xan))
= ( − 1 ) n + 1 ∑ i = 1 n a i ∏ j = 1 n a j =(-1)^{n+1}\sum_{i=1}^{n}a_i\prod_{j=1}^{n}a_j =(1)n+1i=1naij=1naj

n = 1 , k = 2 n=1,k=2 n=1,k=2时,两处的特判可以相互抵消,于是可以不需要特判。

于是只要维护 ∑ i = 1 n a i \sum_{i=1}^{n}a_i i=1nai ∏ i = 1 n a i \prod_{i=1}^{n}a_i i=1nai ∑ i = 1 n ∏ j ≠ i a j \sum_{i=1}^{n}\prod_{j\not=i}a_j i=1nj=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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值