CF446C题解

考虑 \(\sqrt{5}\) 在模这个质数的意义下有值,可以将 \(f_n\) 拆成 \(x^n+y^n\)

那么问题变成了给加上 \(i\in[l,r]\)\(i\) 加上 \(x^{i-l+1}\),求区间和。

线段树处理这种东西不是很方便,考虑分块。

对于散块显然可以直接暴力加,对于整块加将操作变为 \(x^{i-L+1}\times x^t\)\(L\) 是该块的左端点),直接打标记即可。

对于询问,整块询问和散块询问都十分显然。

复杂度 \(O(m\sqrt{n})\) 应该没啥问题。

实际上如果不存在 \(\sqrt{5}\) 也可以考虑 \(f_n=V\times(x^n\pmod{1-P(x)})\),然后维护右边的玩意儿。

upd:polylog 的做法很简单,我真是菜到家了/kk

考虑令 \(a[i]=x^i\),那么每次操作相当于令 \(b[i]+=x^{1-l}\),相当于区间加。

用线段树随便维护一下即可。。。

#include<cstdio>
#include<cctype>
const int M=3e5+5,mod=1e9+9,sqrt5=383008016,isqrt5=276601605,x=mod+1+sqrt5>>1,y=mod+1-sqrt5>>1;
int n,m,S[M],S1[M<<2],S2[M<<2],sum[M<<2],tag1[M<<2],tag2[M<<2];
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline void write(int n){
	static char s[15];int top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top]),--top);putchar(10);
}
inline int pow(int a,int b=mod-2){
	int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
inline void push(const int&u,const int&x,const int&y){
	sum[u]=(sum[u]+1ll*x*S1[u]+1ll*y*S2[u])%mod;tag1[u]=(tag1[u]+x)%mod;tag2[u]=(tag2[u]+y)%mod;
}
inline void pushdown(const int&u){
	if(!tag1[u]&&!tag2[u])return;push(u<<1,tag1[u],tag2[u]);push(u<<1|1,tag1[u],tag2[u]);tag1[u]=tag2[u]=0;
}
inline void update(const int&u){
	sum[u]=(sum[u<<1]+sum[u<<1|1])%mod;
}
inline void Build(const int&u,const int&L=1,const int&R=n){
	if(L==R)return S1[u]=pow(x,L),S2[u]=pow(y,L),void();
	const int&mid=L+R>>1;Build(u<<1,L,mid);Build(u<<1|1,mid+1,R);
	S1[u]=(S1[u<<1]+S1[u<<1|1])%mod;S2[u]=(S2[u<<1]+S2[u<<1|1])%mod;update(u);
}
inline void Mdf(const int&u,const int&l,const int&r,const int&x,const int&y,const int&L=1,const int&R=n){
	if(l>R||L>r)return;if(l<=L&&R<=r)return push(u,x,y);pushdown(u);
	const int&mid=L+R>>1;Mdf(u<<1,l,r,x,y,L,mid);Mdf(u<<1|1,l,r,x,y,mid+1,R);update(u);
}
inline int Qry(const int&u,const int&l,const int&r,const int&L=1,const int&R=n){
	if(l>R||L>r)return 0;if(l<=L&&R<=r)return sum[u];pushdown(u);
	const int&mid=L+R>>1;return(Qry(u<<1,l,r,L,mid)+Qry(u<<1|1,l,r,mid+1,R))%mod;
}
signed main(){
	n=read();m=read();Build(1);
	for(int i=1;i<=n;++i)S[i]=(S[i-1]+read())%mod;
	for(int i=1;i<=m;++i){
		int opt,l,r;opt=read();l=read();r=read();
		if(opt==1)Mdf(1,l,r,pow(x,mod-l),mod-pow(y,mod-l));
		if(opt==2)write((1ll*isqrt5*Qry(1,l,r)%mod+mod+S[r]-S[l-1])%mod);
	}
}
posted @ 2022-07-22 16:31  Prean  阅读(86)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};