C. DZY Loves Fibonacci Numbers

发布时间 2023-09-07 21:12:57作者: 久远寺冇珠

题意:给你一个长度为n的序列,然后有m次操作,操作分两种:

  1,给出l,r,让你对该区间每一个数加上对应的斐波那契数列的数,举例,a[l]+1,a[l+1]+1,a[l+2]+2……。

  2,给出l,r,让你对该区间的数求和,mod 1e9+9(tmd我写的1e9+7,debug浪费了一个小时,上床的时候都两点多了)

解法:首先对于一个类斐波那契数列,我们可以发下如下性质。

  1,(n)=fab[n-2]*(1)+fab[n-1]*(2)

  2,sum(n)如何求呢?结合上一条,然后列出表来,发现没有规律,然后我们做一个差分,就发现性质了。于是有

  sum(n)=fab[n]+sfab[n-1]。同时这里要注意边界。

  然后我们就能用线段树来维护了,懒标记开两个,分别维护第一个fab数和第二个fab数,当然尤其要注意边界,就是区间长度为1或2的时候,上面的规律不一定成立,特判就好啦。2点上床这个也贡献了一大部分。

  

// LUOGU_RID: 123922167
#include<bits/stdc++.h>
#define de cout<<111<<"\n";
#define fi first
#define se second
#define ll long long
#define kx(a,b) ((a*b)%mod)
#define kplus(a,b) ((a+b)%mod)
#define lowbit(x) x&(-x);
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define lk k<<1
#define rk k<<1|1
#define up(a,b) ((a-1ll)/b+1ll)
typedef __int128 Int;
using namespace std;
const int N=300010;
//const ll mod=998244353;
const int mod=1000000009;
typedef pair<int,int> pii;
ll fect[N], infect[N];
ll binpow(ll a,ll b,ll c){
    ll ans=1;
    while(b){
        if(b&1)
            ans=(Int)ans*a%c;
        a=(Int)a*a%c;
        b>>=1;
    }
    return ans;}
int C(int a,int b){
    return fect[a]*infect[b]%mod*infect[a-b]%mod;}
void initzuhe(int n){
    fect[0]=1;infect[0]=1;
    for(int i=1;i<=n;i++){
        fect[i]=(fect[i-1]*i)%mod;
    }
    infect[n-1]=binpow(fect[n-1],mod-2ll,mod);
    for(int i=n-2;i>=1;i--)
        infect[i]=infect[i+1]*(i+1ll)%mod;}
ll test[12]={2,3,5,7,11,13,17,19,23,29,31,37},maxn;
bool check(ll a,ll n){
    ll d=n-1,get=binpow(a,d,n);
    if(get!=1) return 1;
    while((d&1)^1)
        if(d>>=1,(get=binpow(a,d,n))==n-1) return 0;
        else if(get!=1) return 1;
    return 0;}
bool miller_rabbin(ll n)
{
    if(n<40){
        for(int i=0;i<12;i++) if(test[i]==n) return 1;
        return 0;
    }
    for(int i=0;i<12;i++) if(check(test[i],n)) return 0;
    return 1;}
ll gcd(ll a,ll b){
    return !b?a:gcd(b,a%b);}
inline ll f(ll x,ll c,ll n){
    return ((Int)x*x+c)%n;}
ll pollard_rho(ll x){
    ll s=0,t=0,c=1ll*rand()%(x-1)+1,val=1;
    for(int i=1;;i<<=1,s=t,val=1){
        for(int j=1;j<=i;j++){
            t=f(t,c,x);
            val=(Int)val*abs(t-s)%x;
            if(!(j%127)){
                ll d=gcd(val,x);
                if(d>1) return d;
            }
        }
        ll d=gcd(val,x);
        if(d>1) return d;
    }}
ll x,y;
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1ll,y=0ll;
        return a;
    }
    ll temp=exgcd(b,a%b,x,y);
    ll z=x;x=y;
    y=z-a/b*y;
    return temp;
}
ll fab[300010],sfab[300010];
struct kkk{
    ll a,x,y;
}seg[N<<2];
void build(int k,int l,int r){
    seg[k].x=seg[k].y=0;
    if(l==r){cin>>seg[k].a;return ;}
    int mid=l+r>>1;
    build(lson),build(rson);
    seg[k].a=kplus(seg[lk].a,seg[rk].a);
}
int calrf(int xx,int yy,int len){
    if(len==1)return xx;
    if(len==2)return yy;
    return kplus(kx(fab[len-2],xx),kx(fab[len-1],yy));
}
int calsum(int xx,int yy,int len){
    if(len==1)return xx;
    if(len==2)return kplus(xx,yy);
    return kplus(kx(xx,fab[len]),kx(yy,sfab[len-1]));
}
void pushdown(int k,int l,int r){
    if(l==r)return ;
    int mid=l+r>>1;
    ll lenl=mid-l+1,lenr=r-mid;
    ll r1=calrf(seg[k].x,seg[k].y,lenl+1);
    ll r2=calrf(seg[k].x,seg[k].y,lenl+2);
    ll l1=seg[k].x,l2=seg[k].y;
    seg[lk].a=kplus(seg[lk].a,calsum(l1,l2,lenl));
    seg[rk].a=kplus(seg[rk].a,calsum(r1,r2,lenr));
    seg[lk].x=kplus(seg[lk].x,l1);seg[lk].y=kplus(seg[lk].y,l2);
    seg[rk].x=kplus(seg[rk].x,r1);seg[rk].y=kplus(seg[rk].y,r2);
    seg[k].x=0,seg[k].y=0;
}
void update(int k,int l,int r,int x,int y){
    pushdown(k,l,r);
    if(x<=l&&r<=y){
        ll len=r-l+1;
        seg[k].a=kplus(seg[k].a,calsum(fab[l-x+1],fab[l-x+2],len));
        seg[k].x=fab[l-x+1];
        seg[k].y=fab[l-x+2];
        return ;
    }
    int mid=l+r>>1;
    if(x<=mid)update(lson,x,y);
    if(y>mid)update(rson,x,y);
    seg[k].a=kplus(seg[lk].a,seg[rk].a);
}
ll query(int k,int l,int r,int x,int y){
    pushdown(k,l,r);
    if(x<=l&&r<=y){
        return seg[k].a;
    }
    int mid=l+r>>1;
    ll res=0ll;
    if(x<=mid)res=kplus(res,query(lson,x,y));
    if(y>mid)res=kplus(res,query(rson,x,y));
    return res;
}
void bugseg(int k,int l,int r){
    cout<<k<<" "<<l<<" "<<r<<" "<<seg[k].a<<" "<<seg[k].x<<" "<<seg[k].y<<"\n";
    if(l==r)return ;
    int mid=l+r>>1;
    bugseg(lson);bugseg(rson);
}
void solve(){
    int n,m;cin>>n>>m;
    build(1,1,n);
    while(m--){
        int op;cin>>op;
        if(op==1){
            int x,y;cin>>x>>y;
            update(1,1,n,x,y);
        }
        else{
            int x,y;cin>>x>>y;
            cout<<query(1,1,n,x,y)<<"\n";
        }
        //bugseg(1,1,n);
    }
}
signed main(){
     std::ios::sync_with_stdio(false);
     std::cin.tie(0);
     std::cout.tie(0);
    srand((unsigned)time(NULL));
    fab[1]=1ll;fab[2]=1ll;
    sfab[1]=1ll;sfab[2]=2ll;
    for(int i=3;i<=300000;i++){
        fab[i]=kplus(fab[i-1],fab[i-2]);
        sfab[i]=kplus(sfab[i-1],fab[i]);
    }
    //int t;cin>>t;while(t--)
    solve();
}