• [CF 446C] DZY Loves Fibonacci Numbers


    题目要求维护一个数据结构,支持区间依次加斐波那契数列,区间求和。
    一开始我想的是利用斐波那契数列前缀和公式,然后下传,类似于维护一个等差数列,但是很快我就发现这个思路有问题。
    但是这个思路其实有用,我们考察一下斐波那契数列的通项公式:
    (f_n = frac{1}{sqrt{5}} [(frac{1 + sqrt{5}}{2})^n - (frac{1 - sqrt{5}}{2})^n])

    其实斐波那契数列可以看成两个等比数列之差。本题要求取模,所以我们不妨求一下(sqrt{5})在模(10^9+9)意义下的模数,通过抄题解计算可以得到其模数为383008016,然后就可以愉快的维护两个等比数列了。
    维护方法比较简单,显然公比一定,只需要下传首项即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<vector>
    #include<set>
    #include<map>
    #include<string>
    #include<iostream>
    #include<queue>
    #include<cctype>
    using namespace std;
    
    #define A(x) cout << #x << " " << x << endl;
    #define AA(x,y) cout << #x << " " << x << #y << " " << y << endl;
    #define B cout << "Break" << endl;
    #define ll long long
    #define inf 1000000000
    
    ll read()
    {
    	ll c = getchar();
    	int x = 0,f = 1;
    	while(!isdigit(c))
    	{
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(isdigit(c))
    	{
    		x = x * 10 + c - '0';
    		c = getchar();
    	}
    	return f * x;
    }
    #define N 300010
    #define mod 1000000009
    ll base1,base2,inv,n,m;
    int seq[N];
    ll quick_pow(ll a,ll b)
    {
    	ll ret = 1;
    	while(b)
    	{
    		if(b & 1) ret = ret * a % mod;
    		a = a * a % mod;
    		b >>= 1;
    	}
    	return ret % mod;
    }
    struct Segment_Tree
    {
    	#define mid (l + r >> 1)
    	#define ls x << 1,l,mid
    	#define rs x << 1 | 1,mid + 1,r
    	ll p[N],tree[N << 2],lazy[N << 2],q,Inv;
    	void init()
    	{
    		p[0] = 1;
    		for(ll i = 1;i <= n;++i) p[i] = p[i - 1] * q % mod;
    		Inv = quick_pow(q - 1,mod - 2);
    		build(1,1,n);
    		return;
    	}
    	void push_up(ll x)
    	{
    		tree[x] = (tree[x << 1] + tree[x << 1 | 1]) % mod;
    		return;
    	}
    	void build(ll x,ll l,ll r)
    	{
    		if(l == r) return;
    		build(ls);
    		build(rs);
    		push_up(x);
    		return;
    	}
    	void add(ll x,ll l,ll r,ll a)
    	{
    		lazy[x] += a;
    		tree[x] += (a * p[r - l + 1] % mod - a + mod) % mod * Inv % mod;
    		return;
    	}
    	void push_down(ll x,ll l,ll r)
    	{
    		if(!lazy[x]) return;
    		add(ls,lazy[x]);
    		add(rs,lazy[x] * p[r - l + 1] % mod);
    		lazy[x] = 0;
    	}
    	void modify(ll x,ll l,ll r,ll L,ll R,ll a)
    	{
    		if(l == L && r == R)
    		{
    			add(x,l,r,a);
    			return;
    		}
    		push_down(x,l,r);
    		if(r <= mid) modify(ls,L,R,a);
    		else if(l > mid) modify(rs,L,R,a);
    		else
    		{
    			modify(ls,L,mid,a);
    			modify(rs,mid + 1,R,a * p[mid - L + 1] % mod);
    		}
    		push_up(x);
    		return;
    	}
    	ll query(ll x,ll l,ll r,ll L,ll R)
    	{
    		if(l == L && r == R) return tree[x];
    		push_down(x,l,r);
    		if(r <= mid) return query(ls,L,R);
    		else if(l > mid) return query(rs,L,R);
    		else return (query(ls,L,mid) + query(rs,mid + 1,R)) % mod;
    	}
    
    }t1,t2;
    
    int main()
    {
    	t1.q = (383008016 + 1) * quick_pow(2ll,mod - 2) % mod;
    	t2.q = (1 - 383008016 + mod) * quick_pow(2ll,mod - 2) % mod;
    	inv = quick_pow(383008016,mod - 2);
    
    	n = read(),m = read();
    	for(ll i = 1;i <= n;++i) seq[i] = (seq[i - 1] + read()) % mod;
    	t1.init(),t2.init();
    	while(m--)
    	{
    		ll op = read(),l = read(),r = read();
    		if(op == 1)
    		{
    			t1.modify(1,1,n,l,r,t1.q);
    			t2.modify(1,1,n,l,r,t2.q);
    		}
    		else
    		{
    			ll a = t1.query(1,1,n,l,r);
    			ll b = t2.query(1,1,n,l,r);
    			ll ans = (a - b + mod) % mod * inv % mod;
    			printf("%lld
    ",((seq[r] - seq[l - 1] + mod) % mod + ans) % mod);
    		}
    	}
    
    }
    
  • 相关阅读:
    form表单的两种提交方式,submit和button的用法
    ORACLE SEQUENCE用法(转)
    hive优化
    Hive分区表创建、分类
    Hive体系结构
    Hive入门指南
    mysql统计表中条目个数的方法举例
    mysql如何快速创建相同结构的表
    VMware Workstation下VMnet1等虚拟网卡与主机网卡之间的关系
    linux命令详解——lsof
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/12408152.html
Copyright © 2020-2023  润新知